J’ai une application Spring 2.5 / Java / Tomcat. Il y a le haricot suivant, qui est utilisé dans toute 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 haricot est configuré de la sorte (tous les haricots du paquet sont inclus)
Le second bean (nouveau) est configuré séparément
Cela se produit (bien sûr) dans une exception lors du démarrage du serveur:
l’exception nestede est org.springframework.beans.factory.NoSuchBeanDefinitionException: aucun bean unique de type [com.sevenp.mobile.samplemgmt.service.dao.DeviceDao] n’est défini: bean correspondant unique attendu mais trouvé 2: [deviceDao, jdbcDeviceDao]
d’une classe essayant de créer le haricot comme ça
@Autowired private DeviceDao hibernateDevicDao;
car il y a deux beans implémentant la même interface.
Est-il possible de configurer les beans afin que
1. Je n’ai pas besoin de modifier les classes existantes, qui ont déjà HibernateDeviceDao
automatiquement
2. être toujours capable d’utiliser le second (nouveau) bean comme ceci:
@Autowired @Qualifier("jdbcDeviceDao")
C’est-à-dire que j’aurais besoin d’un moyen de configurer le bean HibernateDeviceDao
comme bean par défaut à générer automatiquement, en autorisant simultanément l’utilisation du JdbcDeviceDao
lorsque cela est explicitement spécifié avec l’annotation @Qualifier
.
J’ai essayé de mettre la propriété
autowire-candidate="false"
dans la configuration du bean pour JdbcDeviceDao:
parce que la documentation de spring dit que
Indique si ce haricot doit être pris en compte lors de la recherche de candidats correspondants pour satisfaire aux exigences de démarrage 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 envoyer JdbcDeviceDao
à l’aide de l’annotation @Qualifier
et utiliser le bean par défaut HibernateDeviceDao
. Apparemment, mon interprétation n’était pas correcte, car cela entraîne le message d’erreur suivant au démarrage du serveur:
Dépendance non satisfaite de type [classe com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao]: au moins 1 bean correspondant attendu
venant de la classe où j’ai essayé de lancer le haricot avec un qualificatif:
@Autowired @Qualifier("jdbcDeviceDao")
La suggestion de skaffman d’essayer l’annotation @Resource a fonctionné. Donc, la configuration a autowire-candidate définie sur false pour jdbcDeviceDao et lors de l’utilisation de jdbcDeviceDao, je m’en réfère à l’aide de l’annotation @Resource (au lieu de @Qualifier):
@Resource(name = "jdbcDeviceDao") private JdbcDeviceListItemDao jdbcDeviceDao;
Je suggère de marquer la classe Hibernate DAO avec @Primary
, c’est-à-dire (en supposant que vous ayez utilisé @Repository
sur HibernateDeviceDao
):
@Primary @Repository public class HibernateDeviceDao implements DeviceDao
De cette façon, il sera sélectionné comme candidat par défaut avec autowire, sans avoir besoin de autowire-candidate
sur l’autre bean.
En outre, plutôt que d’utiliser @Autowired @Qualifier
, je trouve plus élégant d’utiliser @Resource
pour choisir des beans spécifiques, c.-à-d.
@Resource(name="jdbcDeviceDao") DeviceDao deviceDao;
Qu’en est-il de @Primary
?
Indique qu’un bean doit avoir la préférence lorsque plusieurs candidats sont qualifiés pour générer automatiquement une dépendance à valeur unique. Si exactement un bean “principal” existe parmi les candidats, ce sera la valeur automatiquement. Cette annotation est sémantiquement équivalente à l’atsortingbut
primary
l’élémentdans Spring XML.
@Primary public class HibernateDeviceDao implements DeviceDao
Ou si vous souhaitez que votre version de 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 stubed en l’annotant.
Pour Spring 2.5, il n’y a pas de @Primary
. Le seul moyen est d’utiliser @Qualifier
.