自动assembly实现相同接口的两个bean – 如何将默认的bean设置为autowire?

背景:

我有一个Spring 2.5 / Java / Tomcat应用程序。 有下面的bean,在许多地方在整个应用程序中使用

public class HibernateDeviceDao implements DeviceDao 

和下面这个新的bean:

 public class JdbcDeviceDao implements DeviceDao 

第一个bean是这样configuration的(包中的所有bean都包含在内)

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

第二个(新)bean是单独configuration的

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

这导致(当然)在启动服务器时出现exception:

嵌套的exception是org.springframework.beans.factory.NoSuchBeanDefinitionException:没有定义types为[com.sevenp.mobile.samplemgmt.service.dao.DeviceDao]的唯一bean:期望的单个匹配的bean,但find2:[deviceDao,jdbcDeviceDao]

从一个类尝试自动assembly这样的bean

 @Autowired private DeviceDao hibernateDevicDao; 

因为有两个bean实现相同的接口。

问题是:

是否有可能configuration豆,以便

1.我不必对现有的已经有了HibernateDeviceDao自动assembly的类进行修改

2.仍然可以像这样使用第二个(新)bean:

 @Autowired @Qualifier("jdbcDeviceDao") 

也就是说,我需要一种方法来configurationHibernateDeviceDao bean作为自动assembly的默认bean,同时允许在使用@Qualifier批注明确指定时使用JdbcDeviceDao

我已经尝试过了:

我尝试设置属性

 autowire-candidate="false" 

在JdbcDeviceDao的beanconfiguration中:

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

因为Spring的文档就是这样说的

指示在查找匹配的候选项以满足另一个bean的自动assembly要求时,是否应该考虑这个bean。 请注意,这不会影响按名称的显式引用,即使指定的bean未标记为自动连线候选,也会得到解决。

我的解释是,我仍然可以使用@Qualifier批注自动JdbcDeviceDao ,并将HibernateDeviceDao作为默认Bean。 显然我的解释是不正确的,因为这会导致在启动服务器时出现以下错误信息:

types[com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao]types的不完全依赖:预期至less有一个匹配的bean

来自我尝试用限定符自动assemblybean的类:

 @Autowired @Qualifier("jdbcDeviceDao") 

解:

skaffman的 build议尝试@资源注释工作。 所以这个configuration对jdbcDeviceDao的autowire-candidate设置为false,当使用jdbcDeviceDao时,我使用@Resource注解(而不是@Qualifier)引用它:

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

我build议用@Primary标记Hibernate DAO类,即(假设你在HibernateDeviceDao上使用@Primary ):

 @Primary @Repository public class HibernateDeviceDao implements DeviceDao 

这样它将被选为默认的自动注册候选者,而不需要另一个bean上的autowire-candidate

此外,而不是使用@Autowired @Qualifier ,我发现它更优雅的使用@Resourceselect特定的豆,即

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

那么@Primary呢?

指示当多个候选者有资格自动装入单值依赖关系时,应该给予一个bean 优先 。 如果候选人中只有一个“主要”bean,那么这将是自动化的价值。 这个注解在语义上等同于Spring XML中的<bean>元素的primary属性。

 @Primary public class HibernateDeviceDao implements DeviceDao 

或者,如果您希望默认使用您的Jdbc版本:

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

@Primary对于集成testing来说也是非常棒的,当你可以通过注释来轻松地replace生产bean的时候。

对于Spring 2.5,没有@Primary 。 唯一的方法是使用@Qualifier