Autowiring two beans implementing same interface - how to set default bean to autowire?
autowired, java, spring, spring-mvc
Solution
I'd suggest marking the Hibernate DAO class with `@Primary`, i.e. (assuming you used `@Repository` on `HibernateDeviceDao`):
@Primary
@Repository
public class HibernateDeviceDao implements DeviceDao
This way it will be selected as the default autowire candididate, with no need to `autowire-candidate` on the other bean.
Also, rather than using `@Autowired @Qualifier`, I find it more elegant to use `@Resource` for picking specific beans, i.e.
@Resource(name="jdbcDeviceDao")
DeviceDao deviceDao;
Problem
Background: I have a Spring 2.5/Java/Tomcat application. There is the following bean, which is used throughout the application in many places ``` public class HibernateDeviceDao implements DeviceDao ``` and the following bean which is new: ``` public class JdbcDeviceDao implements DeviceDao ``` The first bean is configured so (all beans in the package are included) ``` <context:component-scan base-package="com.initech.service.dao.hibernate" /> ``` The second (new) bean is configured separately ``` <bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao"> <property name="dataSource" ref="jdbcDataSource"> </bean> ``` This results (of course) in an exception when starting the server: nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.sevenp.mobile.samplemgmt.service.dao.DeviceDao] is defined: expected single matching bean but found 2: [deviceDao, jdbcDeviceDao] from a class trying to autowire the bean like this ``` @Autowired private DeviceDao hibernateDevicDao; ``` because there are two beans implementing the same interface. The question: Is it possible to configure the beans so that 1. I don't have to make changes to existing classes, which already have the `HibernateDeviceDao` autowired 2. still being able to use the second (new) bean like this: ``` @Autowired @Qualifier("jdbcDeviceDao") ``` I.e. i would need a way to configure the `HibernateDeviceDao` bean as the default bean to be autowired, simultaneously allowing the usage of a the `JdbcDeviceDao` when explicitly specifying so with the `@Qualifier` annotation. What I've already tried: I tried setting the property ``` autowire-candidate="false" ``` in the bean configuration for JdbcDeviceDao: ``` <bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao" autowire-candidate="false"> <property name="dataSource" ref="jdbcDataSource"/> </bean> ``` because the Spring documentation says that Indicates whether or not this bean should be considered when looking for matching candidates to satisfy another bean's autowiring requirements. Note that this does not affect explicit references by name, which will get resolved even if the specified bean is not marked as an autowire candidate.* which I interpreted to mean that I could still autowire `JdbcDeviceDao` using the `@Qualifier` annotation and have the `HibernateDeviceDao` as default bean. Apparently my interpretation was not correct, though, as this results in the following error message when starting the server: Unsatisfied dependency of type [class com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao]: expected at least 1 matching bean coming from the class where I've tried autowiring the bean with a qualifier: ``` @Autowired @Qualifier("jdbcDeviceDao") ``` Solution: skaffman's suggestion to try the @Resource annotation worked. So the configuration has autowire-candidate set to false for jdbcDeviceDao and when using the jdbcDeviceDao I refer to it using the @Resource annotation (instead of @Qualifier): ``` @Resource(name = "jdbcDeviceDao") private JdbcDeviceListItemDao jdbcDeviceDao; ```