以春季@Autowired和@Qualifier后为参考
我们有这个例子来修复自动接线冲突:
public interface Vehicle {
public void start();
public void stop();
}
有两个 bean,Car
和Bike
实现Vehicle
接口。
@Component(value="car")
public class Car implements Vehicle {
@Override
public void start() {
System.out.println("Car started");
}
@Override
public void stop() {
System.out.println("Car stopped");
}
}
@Component(value="bike")
public class Bike implements Vehicle {
@Override
public void start() {
System.out.println("Bike started");
}
@Override
public void stop() {
System.out.println("Bike stopped");
}
}
@Component
public class VehicleService {
@Autowired
@Qualifier("bike")
private Vehicle vehicle;
public void service() {
vehicle.start();
vehicle.stop();
}
}
这是解决此问题的一个很好的例子。
但是当我遇到同样的问题但在应用程序上下文中没有这些应答器时:
<context:component-scan></context:component-scan>
<context:annotation-config></context:annotation-config>
所有问题都可以通过使用@Qualifier
注释来解决,但就我而言,我们不使用允许使用注释的应答器。
问题是:
如何在不使用注释的情况下仅使用应用程序上下文中的配置来解决此问题?
我搜索了很多,我发现人们在 bean 声明中谈论autowire
属性<bean id="dao" class="package.IDao" autowire="byName"></bean>
我需要更多解释。
如何仅使用应用程序中的配置解决此问题 上下文?
您可以使用如下所示的qualifier
标签(请参阅 https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-autowired-annotation-qualifiers)
<context:annotation-config/>
<beans>
<bean class="your_pkg_route.Vehicle">
<qualifier value="bike"/>
</bean>
</beans>
</context:annotation-config>
我发现人们在 bean 中谈论自动连线属性 声明,我需要更多解释
使用批注
在 Bean 声明方法上使用@Autowired
通过(另一个)声明的 Bean 注入定义的依赖项。现在,如果你的依赖项在应用程序的同一上下文中,你根本不需要使用@Autowired
注释,因为 Spring 能够自己弄清楚它们。因此,如果您的依赖项在应用程序上下文之外,则可以使用它。
例如,参考以下代码:
@Autowired
@Bean
public MyBean getMybean(Dependency1 depdency1, Dependency2 depdency2) {
return new MyBean(depdency1.getSomeStuff(), depdency2.getSomeOtherStuff());
}
在这里,@Autowired
将找到Dependency1
和Dependency2
的实例,并将提供它们来创建MyBean
的实例。
使用 xml 配置
从临弹簧 5...Spring 支持五种自动接线模式。
byName
:使用自动布线时byName
,Spring 会尝试将每个属性连接到同名的 bean。因此,如果目标 Bean 具有名为foo
的属性,并且在ApplicationContext
中定义了foo
Bean,则foo
Bean 将分配给目标的foo
属性。byType
: 使用byType
自动接线时,Spring 会尝试连接每个 目标 Bean 的属性,通过自动使用 中相同类型的 BeanApplicationContext
.constructor
:此功能就像byType
接线一样,只是它使用构造函数而不是二传手来执行注入。Spring 尝试在构造函数中匹配最大数量的参数。所以,如果你的 bean 有两个构造函数,一个接受String
,一个接受String
和一个Integer
,并且你的ApplicationContext
中同时有一个String
和一个Integer
bean,Spring 使用双参数构造函数。default
: 弹簧将在constructor
和byType
模式之间进行选择 自然而然。如果你的bean有一个默认的(无参数)构造函数,Spring 使用byType
;否则,它使用构造函数。no
:这是默认值
所以,在你的情况下,你需要做这样的事情(但是,我不推荐它。为什么?,你需要将Vehicle
类声明为一个不正确的 bean 和一个组件,请参阅 Spring:@Component 与 @Bean。另一方面,我不确定您是否可以仅将其声明为豆子而使用它):
// xml config
<context:annotation-config/>
<beans>
// use the primary tag here too! in order to say this the primary bean
// this only works when there are only two implementations of the same interface
<bean id="bike" primary="true" class="your_pkg_route.Bike"/>
<bean id="car" class="your_pkg_route.Car"/>
<bean autowire="byName" class="your_pkg_route.VehicleService"/>
<beans>
</context:annotation-config>
// VehicleService
@Component
public class VehicleService {
private Vehicle bike; // call attribute 'bike' so it is autowired by its name
public void service() {
//...
}
}
如您所见,尝试使用 xml 配置执行此操作有很多复杂性,因此我建议您尽可能使用注释选项。
相关文章:
- 为什么在 Spring 配置类中不需要@Autowired@Bean方法?
- @Bean和@Autowired的区别
PS:我没有测试任何发布的代码。
您可以使用@Primary而不是@Qualifier
@Primary
@Component(value="bike")
public class Bike implements Vehicle {
当有多个相同类型的 bean 时,我们使用 @Primary 来赋予更高的优先级。
我们可以直接在豆子上使用@Primary
您还可以在 XML 中设置主要属性:
属性具有主要属性:
<bean primary="true|false"/>
如果通过 XML 声明@Primary注释类,则会忽略@Primary注释元数据,而是遵循。