自动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
,我发现它更优雅的使用@Resource
select特定的豆,即
@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
。