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;
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;
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>
elementuprimary
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ą.
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
.
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