自动布线两个实现相同接口的bean - 如何将默认Bean设置为autowire?

2022-08-31 07:46:37

背景:

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

public class HibernateDeviceDao implements DeviceDao

以及以下新的豆子:

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: No unique bean type [com.sevenp.mobile.samplemgmt.service.dao.DeviceDao] 已定义:预期的单个匹配 bean 但发现 2: [deviceDao, jdbcDeviceDao]

来自一个试图像这样自动连接豆子的类

@Autowired
private DeviceDao hibernateDevicDao;

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

问题:

是否可以配置豆子,以便

1.我不必对现有类进行更改,这些类已经具有自动连接HibernateDeviceDao

2.仍然能够像这样使用第二个(新)豆:

@Autowired
@Qualifier("jdbcDeviceDao")

也就是说,我需要一种方法将bean配置为要自动连接的默认bean,同时允许在注释中显式指定时使用the。HibernateDeviceDaoJdbcDeviceDao@Qualifier

我已经尝试过了:

我尝试设置属性

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 未标记为自动连接候选项,也会解析显式引用。

我将其解释为我仍然可以使用注释自动连接并将bean作为默认bean。但是,显然我的解释不正确,因为这会导致在启动服务器时出现以下错误消息:JdbcDeviceDao@QualifierHibernateDeviceDao

类型 [class com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao] 的未满足依赖关系:预期至少 1 个匹配的 Bean

来自我尝试过使用限定符自动连接bean的类:

@Autowired
@Qualifier("jdbcDeviceDao")

溶液:

skaffman关于尝试@Resource注释的建议奏效了。因此,对于jdbcDeviceDao,配置将自动布线候选设置为false,并且在使用jdbcDeviceDao时,我使用@Resource注释(而不是@Qualifier)来引用它:

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

答案 1

我建议用@Primary标记Hibernate DAO类,即(假设你使用了):@RepositoryHibernateDeviceDao

@Primary
@Repository
public class HibernateDeviceDao implements DeviceDao

这样,它将被选为默认的自动布线候选项,而无需在另一个豆子上。autowire-candidate

另外,我发现使用而不是使用,它更优雅地用于挑选特定的豆类,即@Autowired @Qualifier@Resource

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

答案 2

@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当您可以通过注释来轻松地将生产Bean替换为存根版本时,它也非常适合集成测试。


推荐