背景:
我有一个 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>
这会导致(当然)在启动服务器时出现异常:
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]
来自一个试图像这样 Autowiring bean 的类
@Autowired
private DeviceDao hibernateDevicDao;
因为有两个 bean 实现了相同的接口(interface)。
问题:
是否可以配置 bean 以便
1.我不必更改现有的类,它们已经 Autowiring 了 HibernateDeviceDao
2. 仍然可以像这样使用第二个(新)bean:
@Autowired
@Qualifier("jdbcDeviceDao")
即我需要一种方法来将 HibernateDeviceDao
bean 配置为要 Autowiring 的默认 bean,同时允许在使用 @ 明确指定时使用
注释。 JdbcDeviceDao
限定符
我已经尝试过的:
我尝试设置属性
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 文档是这么说的
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.*
我解释为我仍然可以使用 @Qualifier
注释 Autowiring JdbcDeviceDao
并将 HibernateDeviceDao
作为默认 bean。不过,显然我的解释是不正确的,因为这会在启动服务器时导致以下错误消息:
Unsatisfied dependency of type [class com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao]: expected at least 1 matching bean
来 self 尝试使用限定符 Autowiring bean 的类:
@Autowired
@Qualifier("jdbcDeviceDao")
解决方案:
skaffman's suggestion尝试 @Resource 注释工作。因此配置将 jdbcDeviceDao 的 autowire-candidate 设置为 false 并且在使用 jdbcDeviceDao 时我使用 @Resource 注释(而不是 @Qualifier)来引用它:
@Resource(name = "jdbcDeviceDao")
private JdbcDeviceListItemDao jdbcDeviceDao;
最佳答案
我建议用 @Primary
标记 Hibernate DAO 类,即(假设您在 HibernateDeviceDao
上使用了 @Repository
):
@Primary
@Repository
public class HibernateDeviceDao implements DeviceDao
这样它将被选为默认的 Autowiring 候选者,而无需在另一个bean上autowire-candidate
。
另外,我发现使用 @Resource
来挑选特定的 bean 比使用 @Autowired @Qualifier
更优雅,即
@Resource(name="jdbcDeviceDao")
DeviceDao deviceDao;
关于java - Autowiring 两个实现相同接口(interface)的 bean - 如何将默认 bean 设置为 Autowiring ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10534053/