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

sim*_*mon 132 java spring spring-mvc autowired

背景:

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

public class HibernateDeviceDao implements DeviceDao
Run Code Online (Sandbox Code Playgroud)

和以下新的bean:

public class JdbcDeviceDao implements DeviceDao
Run Code Online (Sandbox Code Playgroud)

第一个bean配置为(包括所有bean)

<context:component-scan base-package="com.initech.service.dao.hibernate" />
Run Code Online (Sandbox Code Playgroud)

第二个(新)bean是单独配置的

<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
    <property name="dataSource" ref="jdbcDataSource">
</bean>
Run Code Online (Sandbox Code Playgroud)

当然,这会导致启动服务器时出现异常:

嵌套异常是org.springframework.beans.factory.NoSuchBeanDefinitionException:没有定义类型为[com.sevenp.mobile.samplemgmt.service.dao.DeviceDao]的唯一bean:期望的单个匹配bean但找到2:[deviceDao,jdbcDeviceDao]

从一个试图像这样自动装豆的类

@Autowired
private DeviceDao hibernateDevicDao;
Run Code Online (Sandbox Code Playgroud)

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

问题:

是否可以配置bean以便这样做

1.我不必对已经HibernateDeviceDao自动装配的现有类进行更改

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

@Autowired
@Qualifier("jdbcDeviceDao")
Run Code Online (Sandbox Code Playgroud)

即我需要一种方法将HibernateDeviceDaobean 配置为要自动装配的默认bean,同时允许在使用注释JdbcDeviceDao显式指定时使用@Qualifier.

我已经尝试过的:

我试过设置属性

autowire-candidate="false"
Run Code Online (Sandbox Code Playgroud)

在JdbcDeviceDao的bean配置中:

<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao" autowire-candidate="false">
    <property name="dataSource" ref="jdbcDataSource"/>
</bean>
Run Code Online (Sandbox Code Playgroud)

因为Spring文档说明了这一点

指示在查找匹配候选项以满足另一个bean的自动装配要求时是否应考虑此Bean.请注意,这不会影响名称的显式引用,即使指定的bean未标记为autowire候选,也会解析引用.*

我解释为我仍然可以JdbcDeviceDao使用@Qualifier注释自动装配并具有HibernateDeviceDao默认bean.显然,我的解释是不正确的,因为这会在启动服务器时导致以下错误消息:

类型[class com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao]的不满意依赖:预计至少有一个匹配的bean

来自我尝试使用限定符自动装配bean的类:

@Autowired
@Qualifier("jdbcDeviceDao")
Run Code Online (Sandbox Code Playgroud)

解:

skaffman 建议尝试@Resource注释工作.因此,对于jdbcDeviceDao,配置的autowire-candidate设置为false,当使用jdbcDeviceDao时,我使用@Resource注释(而不是@Qualifier)来引用它:

@Resource(name = "jdbcDeviceDao")
private JdbcDeviceListItemDao jdbcDeviceDao;
Run Code Online (Sandbox Code Playgroud)

ska*_*man 128

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

@Primary
@Repository
public class HibernateDeviceDao implements DeviceDao
Run Code Online (Sandbox Code Playgroud)

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

而且,@Autowired @Qualifier我发现使用@Resource特定的豆子更加优雅,而不是使用它

@Resource(name="jdbcDeviceDao")
DeviceDao deviceDao;
Run Code Online (Sandbox Code Playgroud)


Tom*_*icz 37

怎么样@Primary

指示当多个候选者有资格自动装配单值依赖项时,优先考虑bean.如果候选者中只存在一个"主"bean,则它将是自动装配的值.此批注在语义上等同于Spring XML中的<bean>元素primary属性.

@Primary
public class HibernateDeviceDao implements DeviceDao
Run Code Online (Sandbox Code Playgroud)

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

<bean id="jdbcDeviceDao" primary="true" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
Run Code Online (Sandbox Code Playgroud)

@Primary 当你可以通过注释来轻松替换带有存根版本的生产bean时,它也非常适合集成测试.


bla*_*ang 8

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