自动装配两个实现相同接口的 bean - 如何将默认 bean 设置为自动装配? [英] Autowiring two beans implementing same interface - how to set default bean to autowire?

查看:33
本文介绍了自动装配两个实现相同接口的 bean - 如何将默认 bean 设置为自动装配?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Spring 2.5/Java/Tomcat 应用程序.有下面这个bean,整个应用很多地方都用到了

I have a Spring 2.5/Java/Tomcat application. There is the following bean, which is used throughout the application in many places

public class HibernateDeviceDao implements DeviceDao

以及以下新bean:

public class JdbcDeviceDao implements DeviceDao

第一个bean是这样配置的(包内所有bean都包含)

The first bean is configured so (all beans in the package are included)

<context:component-scan base-package="com.initech.service.dao.hibernate" />

单独配置第二个(新)bean

The second (new) bean is configured separately

<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
    <property name="dataSource" ref="jdbcDataSource">
</bean>

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

This results (of course) in an exception when starting the server:

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

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]

来自一个试图像这样自动装配 bean 的类

from a class trying to autowire the bean like this

@Autowired
private DeviceDao hibernateDevicDao;

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

because there are two beans implementing the same interface.

是否可以配置bean以便

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

1. I don't have to make changes to existing classes, which already have the HibernateDeviceDao autowired

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

2. still being able to use the second (new) bean like this:

@Autowired
@Qualifier("jdbcDeviceDao")

即我需要一种方法来将 HibernateDeviceDao bean 配置为要自动装配的默认 bean,同时在使用 @ 明确指定时允许使用 JdbcDeviceDao限定符注解.

I.e. i would need a way to configure the HibernateDeviceDao bean as the default bean to be autowired, simultaneously allowing the usage of a the JdbcDeviceDao when explicitly specifying so with the @Qualifier annotation.

我尝试设置属性

autowire-candidate="false"

在 JdbcDeviceDao 的 bean 配置中:

in the bean configuration for JdbcDeviceDao:

<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao" autowire-candidate="false">
    <property name="dataSource" ref="jdbcDataSource"/>
</bean>

因为 Spring 文档说

because the Spring documentation says that

表示在什么时候应该考虑这个bean寻找匹配的候选人以满足另一个 bean自动装配要求.注意这不影响显式按名称引用,即使指定了,也会得到解析bean 未标记为自动装配候选对象.*

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 注释自动装配 JdbcDeviceDao 并将 HibernateDeviceDao 作为默认 bean.不过,显然我的解释不正确,因为这会导致在启动服务器时出现以下错误消息:

which I interpreted to mean that I could still autowire JdbcDeviceDao using the @Qualifier annotation and have the HibernateDeviceDao as default bean. Apparently my interpretation was not correct, though, as this results in the following error message when starting the server:

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

Unsatisfied dependency of type [class com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao]: expected at least 1 matching bean

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

coming from the class where I've tried autowiring the bean with a qualifier:

@Autowired
@Qualifier("jdbcDeviceDao")

解决方案:

skaffman's 建议 尝试使用 @Resource 注释.因此,配置将 jdbcDeviceDao 的 autowire-candidate 设置为 false,并且在使用 jdbcDeviceDao 时,我使用 @Resource 注释(而不是 @Qualifier)来引用它:

Solution:

skaffman's suggestion to try the @Resource annotation worked. So the configuration has autowire-candidate set to false for jdbcDeviceDao and when using the jdbcDeviceDao I refer to it using the @Resource annotation (instead of @Qualifier):

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

推荐答案

我建议用 @Primary,即(假设您使用了 @RepositoryHibernateDeviceDao):

@Primary
@Repository
public class HibernateDeviceDao implements DeviceDao

这样它将被选为默认的自动装配候选者,而无需在另一个 bean 上autowire-candidate.

This way it will be selected as the default autowire candididate, with no need to autowire-candidate on the other bean.

此外,我发现使用 @Resource 来挑选特定的 bean 比使用 @Autowired @Qualifier 更优雅,即

Also, rather than using @Autowired @Qualifier, I find it more elegant to use @Resource for picking specific beans, i.e.

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

这篇关于自动装配两个实现相同接口的 bean - 如何将默认 bean 设置为自动装配?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆