147 votes

Autowiring deux beans implémentant la même interface - comment définir le bean par défaut sur autowire?

Arrière-plan:

J'ai un Ressort 2.5/Java/Tomcat application. Il est le suivant bean, qui est utilisé tout au long de l'application dans de nombreux endroits

public class HibernateDeviceDao implements DeviceDao

et la suite de haricot qui est nouveau:

public class JdbcDeviceDao implements DeviceDao

Le premier haricot est configuré de telle sorte (tous les haricots dans le forfait sont inclus)

<context:component-scan base-package="com.initech.service.dao.hibernate" />

Le deuxième (nouveau) haricot est configuré séparément

<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
    <property name="dataSource" ref="jdbcDataSource">
</bean>

Il en résulte (bien sûr), une exception se produit lors du démarrage du serveur:

exception imbriquée est org.springframework.les haricots.usine.NoSuchBeanDefinitionException: Pas unique bean de type [com.sevenp.mobile.samplemgmt.service.dao.DeviceDao] est défini: unique correspondant bean, mais trouvé 2: [deviceDao, jdbcDeviceDao]

à partir d'une classe en essayant de autowire le haricot comme ceci

@Autowired
private DeviceDao hibernateDevicDao;

parce qu'il y a deux grains de mise en œuvre de la même interface.

La question:

Il est possible de configurer les fèves de sorte que

1. Je n'ai pas à apporter des modifications à des classes existantes, qui ont déjà de l' HibernateDeviceDao autocâblés

2. toujours être en mesure d'utiliser le deuxième (nouveau) de haricots comme ceci:

@Autowired
@Qualifier("jdbcDeviceDao")

I. e. j'aurais besoin d'un moyen de configurer le HibernateDeviceDao bean comme la valeur par défaut de la fève à être autocâblés, en permettant simultanément de l'utilisation de l' JdbcDeviceDao lorsque spécifiant explicitement de la sorte avec l' @Qualifier d'annotation.

Ce que j'ai déjà essayé:

J'ai essayé la définition de la propriété

autowire-candidate="false"

dans la configuration spring pour JdbcDeviceDao:

<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao" autowire-candidate="false">
    <property name="dataSource" ref="jdbcDataSource"/>
</bean>

parce que le Printemps documentation dit que

Indique si oui ou non ce bean devrait être considéré lors à la recherche pour la mise en correspondance des candidats pour répondre à une autre de l'haricot permettra à l'autowiring exigences. Notez que cela n'affecte pas explicite références par nom, qui sera résolue, même si l' bean n'est pas marqué comme un autowire candidat.*

qui j'ai interprété pour signifier que je pouvais encore autowire JdbcDeviceDao à l'aide de l' @Qualifier d'annotation et d'avoir l' HibernateDeviceDao comme valeur par défaut bean. Apparemment, mon interprétation n'est pas correcte, même si, comme cela entraîne le message d'erreur suivant lors du démarrage du serveur:

Insatisfait de la dépendance de type [classe com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao]: attendre au moins 1 correspondance bean

venant de la classe où j'ai essayé permettra à l'autowiring le haricot avec un qualificatif:

@Autowired
@Qualifier("jdbcDeviceDao")

Solution:

skaffman la suggestion d'essayer le @annotation de Ressources travaillé. De sorte que la configuration a autowire-candidat à la valeur false pour jdbcDeviceDao et lors de l'utilisation de la jdbcDeviceDao je vous renvoie pour cela à l'aide de @annotation de Ressources (au lieu de @Qualifier):

@Autowired
@Resource(name = "jdbcDeviceDao")
private JdbcDeviceListItemDao jdbcDeviceDao;

138voto

skaffman Points 197885

Je vous suggère de marquage Hibernate classe DAO avec @Primary, c'est à dire (en supposant que vous avez utilisé @Repository sur HibernateDeviceDao):

@Primary
@Repository
public class HibernateDeviceDao implements DeviceDao

De cette manière, il sera sélectionné par défaut autowire candididate, sans avoir besoin d' autowire-candidate sur les autres bean.

Aussi, plutôt que d'utiliser @Autowired @Qualifier, je trouve cela plus élégant d'utiliser @Resource pour le prélèvement spécifique des haricots, c'est à dire

@Resource(name="jdbcDeviceDao")
DeviceDao deviceDao;

41voto

Tomasz Nurkiewicz Points 140462

Qu'en @Primary?

Indique qu'un bean devrait être donné la préférence lorsque plusieurs candidats sont qualifiés pour autowire une valeur unique de la dépendance. Si exactement un "principal" bean existe parmi les candidats, il sera le autocâblés valeur. Cette annotation est sémantiquement équivalent à l' <bean> de l'élément primary attribut au Printemps XML.

@Primary
public class HibernateDeviceDao implements DeviceDao

Ou si vous voulez que votre Jdbc version utilisée par défaut:

<bean id="jdbcDeviceDao" primary="true" class="com.initech.service.dao.jdbc.JdbcDeviceDao">

@Primary est également idéal pour les tests d'intégration quand vous pouvez facilement remplacer la production de haricot avec écrasa version en annotant.

9voto

blang Points 835

Pour Spring 2.5, il n'y a pas de @Primary. Le seul moyen est d'utiliser @Qualifier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X