Autowireing dwa beans implementujące ten sam interfejs - jak ustawić domyślny bean na autowire?

Background:

Mam aplikację Spring 2.5 / Java / Tomcat. Istnieje następująca fasola, która jest używana przez całą aplikację w wielu miejscach

public class HibernateDeviceDao implements DeviceDao

I następująca fasola, która jest nowa:

public class JdbcDeviceDao implements DeviceDao
Pierwsza fasola jest tak skonfigurowana (wszystkie fasole w pakiecie są dołączone)]}
<context:component-scan base-package="com.initech.service.dao.hibernate" />

Druga (Nowa) fasola jest skonfigurowana osobno

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

To powoduje (oczywiście) wyjątek podczas uruchamiania serwera:

Zagnieżdżone wyjątkiem jest org.springframework.fasola.fabryka.NoSuchBeanDefinitionException: No unique bean of type [com.sevenp.mobile.samplemgmt.obsługa.dao.DeviceDao] is defined: expected single matching bean but found 2: [deviceDao, jdbcDeviceDao]

Z klasy próbującej autowireować fasolę w ten sposób

@Autowired
private DeviceDao hibernateDevicDao;

Ponieważ istnieją dwie fasole implementujące ten sam interfejs.

Pytanie:

Czy możliwe jest skonfigurowanie fasoli tak, aby]}

1. nie muszę wprowadzać zmian do istniejących klas, które mają już HibernateDeviceDao autowired

2. nadal jest w stanie użyć drugiej (nowej) fasoli w ten sposób:

@Autowired
@Qualifier("jdbcDeviceDao")

Tzn. potrzebowałbym sposobu skonfigurowania HibernateDeviceDao bean jako domyślnego Bean, który ma być autowirowany, jednocześnie pozwalając na użycie JdbcDeviceDao, gdy jawnie określamy tak za pomocą adnotacji @Qualifier.

Co już próbowałem:

Próbowałem ustawić własność

autowire-candidate="false"

W konfiguracji bean dla JdbcDeviceDao:

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

Ponieważ dokumentacja źródłowa mówi, że

Wskazuje, czy fasola ta powinna być brana pod uwagę, gdy Szukam pasujących kandydatów do zaspokojenia innych potrzeb wymagania dotyczące autowiringu. zauważ, że nie wpływa to na wyraźne odwołania po nazwie, które zostaną rozwiązane nawet jeśli podany bean nie jest oznaczony jako autowire kandydat.*

Co zinterpretowałem w ten sposób, że nadal mogę autowire JdbcDeviceDao używając adnotacji @Qualifier i mieć HibernateDeviceDao jako domyślną fasolę. Najwyraźniej moja interpretacja nie była poprawna, ponieważ skutkuje to następującym komunikatem o błędzie podczas uruchamiania serwera:

Niezaspokojona zależność typu [class com.sevenp.mobile.samplemgmt.obsługa.dao.jdbc.JdbcDeviceDao]: oczekiwano co najmniej 1 pasujących fasoli

Pochodzi z klasy, gdzie Próbowałem autowirować fasolkę z kwalifikatorem:

@Autowired
@Qualifier("jdbcDeviceDao")

Rozwiązanie:

Skaffman ' s sugestia aby spróbować adnotacji @ Resource zadziałała. Tak więc konfiguracja ma ustawioną wartość autowire-candidate na false dla jdbcDeviceDao i kiedy używam jdbcdevicedao odwołuję się do niej używając adnotacji @ Resource (zamiast @ Qualifier): {]}

@Resource(name = "jdbcDeviceDao")
private JdbcDeviceListItemDao jdbcDeviceDao;
Author: Kronen, 2012-05-10

3 answers

Proponuję oznaczyć klasę Hibernate DAO z @Primary, tzn. (zakładając, że użyłeś @Repository na HibernateDeviceDao):

@Primary
@Repository
public class HibernateDeviceDao implements DeviceDao

W ten sposób zostanie wybrana jako domyślna kandydatura autowire, bez potrzeby autowire-candidate na drugiej fasoli.

Poza tym, zamiast używać @Autowired @Qualifier, bardziej eleganckie wydaje mi się użycie @Resource do zbierania określonych ziaren, tj.

@Resource(name="jdbcDeviceDao")
DeviceDao deviceDao;
 111
Author: skaffman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-10 12:35:52

A co z @Primary?

Wskazuje, że bean powinien mieć preferencję , gdy wielu kandydatów jest zakwalifikowanych do autowire zależność o jednej wartości. Jeśli wśród kandydatów istnieje dokładnie jedna "podstawowa" fasola, będzie to wartość autowired. Ta adnotacja jest semantycznie równoważna atrybutowi <bean> elementu primary w XML Spring.

@Primary
public class HibernateDeviceDao implements DeviceDao

Lub jeśli chcesz, aby Twoja wersja Jdbc była używana domyślnie:

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

@Primary jest również świetny do testowania integracji, gdy można łatwo zastąpić wersję produkcyjną wersją stubbed, adnotując ją.

 30
Author: Tomasz Nurkiewicz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-10 12:37:01

Na wiosnę 2.5 Nie Ma @Primary. Jedynym sposobem jest użycie @Qualifier.

 7
Author: blang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-24 14:03:25