Contexte:
J'ai une application Spring 2.5 / Java / Tomcat. Il y a le haricot suivant, qui est utilisé tout au long de l'application dans de nombreux endroits
public class HibernateDeviceDao implements DeviceDao
et le haricot suivant qui est nouveau:
public class JdbcDeviceDao implements DeviceDao
Le premier bean est configuré ainsi (tous les beans du package sont inclus)
<context:component-scan base-package="com.initech.service.dao.hibernate" />
Le deuxième (nouveau) bean est configuré séparément
<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
<property name="dataSource" ref="jdbcDataSource">
</bean>
Cela entraîne (bien sûr) une exception lors du démarrage du serveur:
l'exception imbriquée est org.springframework.beans.factory.NoSuchBeanDefinitionException: aucun bean unique de type [com.sevenp.mobile.samplemgmt.service.dao.DeviceDao] est défini: le bean correspondant unique attendu mais trouvé 2: [deviceDao, jdbcDeviceDao]
d'une classe essayant de filer automatiquement le haricot comme ça
@Autowired
private DeviceDao hibernateDevicDao;
car il y a deux beans implémentant la même interface.
La question:
Est-il possible de configurer les beans pour que
1. Je ne dois pas apporter des modifications aux classes existantes, qui ont déjà HibernateDeviceDao
autowired
2. toujours en mesure d'utiliser le deuxième (nouveau) bean comme ceci:
@Autowired
@Qualifier("jdbcDeviceDao")
C'est-à-dire HibernateDeviceDao
que j'aurais besoin d'un moyen de configurer le bean en tant que bean par défaut à câbler automatiquement, permettant simultanément l'utilisation d'un the JdbcDeviceDao
en le spécifiant explicitement avec l' @Qualifier
annotation.
Ce que j'ai déjà essayé:
J'ai essayé de définir la propriété
autowire-candidate="false"
dans la configuration du bean pour JdbcDeviceDao:
<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao" autowire-candidate="false">
<property name="dataSource" ref="jdbcDataSource"/>
</bean>
parce que la documentation Spring dit que
Indique si ce bean doit ou non être pris en compte lors de la recherche de candidats correspondants pour satisfaire les exigences de câblage automatique d'un autre bean. Notez que cela n'affecte pas les références explicites par nom, qui seront résolues même si le bean spécifié n'est pas marqué comme candidat autowire. *
ce que j'ai interprété comme signifiant que je pouvais toujours JdbcDeviceDao
utiliser l' @Qualifier
annotation et avoir le HibernateDeviceDao
bean par défaut. Apparemment, mon interprétation n'était pas correcte, car cela entraîne le message d'erreur suivant lors du démarrage du serveur:
Dépendance non satisfaite de type [classe com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao]: attendu au moins 1 bean correspondant
venant de la classe où j'ai essayé d'autowiring le bean avec un qualificatif:
@Autowired
@Qualifier("jdbcDeviceDao")
Solution:
La suggestion de skaffman d'essayer l'annotation @Resource a fonctionné. Ainsi, la configuration a autowire-candidate définie sur false pour jdbcDeviceDao et lorsque j'utilise jdbcDeviceDao, je me réfère à lui en utilisant l'annotation @Resource (au lieu de @Qualifier):
@Resource(name = "jdbcDeviceDao")
private JdbcDeviceListItemDao jdbcDeviceDao;
la source
Réponses:
Je vous suggère de marquer la classe Hibernate avec DAO
@Primary
, à savoir ( en supposant que vous utilisez@Repository
surHibernateDeviceDao
):De cette façon, il sera sélectionné comme candidat par défaut du câble automatique, sans avoir besoin de
autowire-candidate
l'autre bean.De plus, plutôt que d'utiliser
@Autowired @Qualifier
, je le trouve plus élégant à utiliser@Resource
pour cueillir des grains spécifiques, c'est-à-direla source
@Resource
annotation, comme je l'ai également suggéré.@Resource
et@Qualifier
, mis à part le fait que le premier est relativement plus récent que le second?Et quoi
@Primary
?Ou si vous souhaitez que votre version Jdbc soit utilisée par défaut:
@Primary
est également idéal pour les tests d'intégration lorsque vous pouvez facilement remplacer le bean de production par une version stubbed en l'annotant.la source
primary=""
attribut était disponible plus tôt. Déclarez simplementHibernateDeviceDao
en XML et excluez-le de l'analyse des composants / annotations.Pour Spring 2.5, il n'y a pas de
@Primary
. Le seul moyen est d'utiliser@Qualifier
.la source
la source
La raison pour laquelle @Resource (name = "{votre nom de classe enfant}") fonctionne mais @Autowired ne fonctionne parfois pas est à cause de la différence de leur séquence de correspondance
Séquence correspondante de @Autowire
Type, Qualifier, Name
Séquence correspondante de @Resource
Name, Type, Qualifier
L'explication plus détaillée peut être trouvée ici:
Annotations d'injection et de ressource et autowired
Dans ce cas, une classe enfant différente héritée de la classe ou de l'interface parent confond @Autowire, car elles sont du même type; Comme @Resource utilise le nom comme première priorité correspondante, cela fonctionne.
la source