问题
背景:
我有一个Spring 2.5 / Java / Tomcat应用程序。有以下bean,在许多地方的整个应用程序中使用
public class HibernateDeviceDao implements DeviceDao
和以下新的bean:
public class JdbcDeviceDao implements DeviceDao
第一个bean配置为(包括所有bean)
<context:component-scan base-package="com.initech.service.dao.hibernate" />
第二个(新)bean是单独配置的
<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
<property name="dataSource" ref="jdbcDataSource">
</bean>
当然,这会导致启动服务器时出现异常:
嵌套异常是org.springframework.beans.factory.NoSuchBeanDefinitionException:没有定义[com.sevenp.mobile.samplemgmt.service.dao.DeviceDao]类型的唯一bean:期望的单个匹配bean但找到2:[deviceDao,jdbcDeviceDao]
从一个试图像这样自动装豆的类
@Autowired
private DeviceDao hibernateDevicDao;
因为有两个bean实现相同的接口。
##问题:
是否可以配置bean以便
**1.**我不必对现有的类进行更改,这些类已经有了77418428自动化
**2.**仍然可以像这样使用第二个(新)bean:
@Autowired
@Qualifier("jdbcDeviceDao")
即我需要一种方法来配置HibernateDeviceDao
bean作为要自动装配的默认bean,同时允许使用theJdbcDeviceDao
,当使用@Qualifier
annotation明确指定时。
##我已经尝试过的:
我试过设置属性
autowire-candidate="false"
在JdbcDeviceDao的bean配置中:
<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao" autowire-candidate="false">
<property name="dataSource" ref="jdbcDataSource"/>
</bean>
因为Spring文档说明了这一点
指示在查找匹配的候选项以满足另一个bean的自动装配要求时是否应该考虑此bean。请注意,这不会影响名称的显式引用,即使指定的bean未标记为autowire候选,也会解析引用。*
我解释为我仍然可以使用@Qualifier
注释autowireJdbcDeviceDao
并使用HibernateDeviceDao
作为默认bean。显然,我的解释是不正确的,因为这会在启动服务器时导致以下错误消息:
类型[class com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao]的不满意依赖:预计至少有1个匹配的bean
来自我尝试使用限定符自动装配bean的类:
@Autowired
@Qualifier("jdbcDeviceDao")
##解决方案:
skaffman'ssuggestion尝试@Resource注释工作。因此,对于jdbcDeviceDao,配置的autowire-candidate设置为false,当使用jdbcDeviceDao时,我使用@Resource注释(而不是@Qualifier)来引用它:
@Resource(name = "jdbcDeviceDao")
private JdbcDeviceListItemDao jdbcDeviceDao;
#1 热门回答(107 赞)
我建议用@Primary
标记Hibernate DAO类,即(假设你使用了@Repository
onHibernateDeviceDao
):
@Primary
@Repository
public class HibernateDeviceDao implements DeviceDao
这样它将被选为默认的autowire候选者,而不需要在另一个bean上使用.autowire-candidate
。
而且,我发现使用@Resource
挑选特定的豆子,而不是使用@Autowired @Qualifier
,
@Resource(name="jdbcDeviceDao")
DeviceDao deviceDao;
#2 热门回答(29 赞)
怎么样@Primary
?
表示当多个候选者有资格自动装配单值依赖项时,应优先考虑bean。如果候选者中只存在一个"主"bean,则它将是自动装配的值。此批注在语义上等同于Spring XML中的<bean>元素的主要属性。
@Primary
public class HibernateDeviceDao implements DeviceDao
或者,如果你希望默认使用Jdbc版本:
<bean id="jdbcDeviceDao" primary="true" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
@Primary
也非常适合集成测试,因为你可以通过注释来轻松替换带有存根版本的生产bean。
#3 热门回答(6 赞)
对于Spring 2.5,没有@Primary
。唯一的方法是使用@Qualifier
。