我们已经知道如何使用
幸运的是,Spring提供了几种技巧,可以帮助我们减少XML的配置数量。
- 自动装配 (autowiring)有助于减少甚至消除
元素和 元素,让Spring自动识别如何装配Bean的依赖关系。 - 自动检测 (autodiscovery)比自动装配更进了一步,让Spring能否自动识别哪些类需要被配置成Spring Bean,从而减少对
元素的使用
当自动装配和自动检测在一起使用时,它们可以显著减少Spring的XML配置数量,通常只需要配置少量的几行XML代码,而无需知道在Spring的应用上下文中究竟有多少Bean。自动装配Bean属性
自动装配分为4种: - byName——寻找和属性名(或者ID)相同的bean自动装配到Bean的对应属性汇总。若找不到,则不进行装配。
- byType——寻找和属性类型相同的bean,找不到,装不上,找到多个抛异常。
- constructor——把与Bean的构造器入参具有相同类型的其他Bean自动装配到Bean构造器的对应入参中。
- autodetect——首先尝试使用constructor进行自动装配。如果失败,再尝试进行byType进行自动装配
每一种装配都有自己的优缺点。
byName自动装配
举个例子说明:
1 | <bean id="kenny2" class="com.springaction.springidol.Instrumentalist"> |
配置文件中显式配置了Kenny的instrument属性。
我们现在修改id为saxophone的bean,修改后:1
<bean id="instrument" class="com.springaction.springidol.Saxophone"/>
修改之后Saxophone的Bean的id属性与Kenny Bean的instrument的属性的名字是一样的,这时就可以配置autowire属性,实现自动装配。
1 | <bean id="kenny2" class="com.springaction.springidol.Instrumentalist" autowire="byName"> |
byName自动装配遵循一项约定:为属性自动装配ID与该属性的名字相同的Bean。通过设置autowire属性为byName,Spring将特殊对待kenny的所有属性,为这些属性寻找与该名字相同的Spring Bean。
byType自动装配
工作方式类似于byName,只不过不在匹配属性的名字而是检查属性的类型。
局限性:应用只允许存在一个Bean与需要装配的属性类型相匹配。
可能会存在多个类型相同的Bean,为了避免因为使用byType带来歧义,我们有两个选择:
- 可以为自动装配标示一个首选Bean
- 可以取消某个Bean自动装配的候选资格。
首选Bean,可以使用的primary属性。如果一个bean属性的primary属性值设置为true,那么该bean将比其他bean优先被选择。但是很诡异的一点是:设置为true之后,所有的Bean都将变成首选Bean,也就不存在首选Bean了。所以,如果使用primary属性,就需要将所有非首选Bean的primary属性设置为false。
constructor自动装配
使用constructor注入来装配Bean,我们可以移除
constructor自动装配和byType自动装配都具有相同的局限性,如果一个类有多个构造器,他们都满足自动装配条件时,Spring是不会猜测哪一个构造器更适合使用。
最佳自动装配
首先尝试constructor自动装配,如果没有发现与构造器相匹配的Bean时,Spring将尝试使用byType自动装配。
默认自动匹配
在根元素
使用注解自动装配
使用注解方式允许更细粒度的自动装配。
spring容器默认禁用注解装配。启用方式:使用Spring的context命名空间配置中的<context:annotation-config />元素。
Spring支持几种不同的用于自动装配的注解。
- Spring自带的@Autowired注解
- JSR-330的@Inject注解
- JSR-250的@Resource注解
使用Autowired
使用@Autowired注解时候,Spring将会尝试对该方法执行byType自动装配
@Autowired注解可以标注setter方法、自动装配Bean应用的任意方法、注解标注属性(就可以删除setter方法了)。当对构造器进行标注时候,即使在spring XML中没有使用
两种阻碍场景:没有匹配到Bean、存在多个匹配的Bean。
解决阻碍,我们可以使用可选的自动装配
可选的自动装配
@Autowired注解具有很强的契约型特征,其标注的属性或参数必须是可装配的。
属性并不一定非要装配,null值也可以接受的场景下,我们通过设置@Autowired的required属性为false来配置自动装配是可选的。1
2@Autowired(require=false)
private Instrument instrument;
当使用@Autowired标注多个构造器时,Spring就会从所有满足装配条件的构造器中选择入参最多的那个构造器。
限定歧义性依赖
假设我们有两个Bean都实现了Instrument接口,这种场景下@Autowired注解没有办法选择哪一个Bean才是真正需要的。这样会抛出异常:NoSuchBeanDefinitionException异常,装配失败。但是我们可以使用@Qualifier注解来明确指定需要装配的bean。1
2
3@Autowired
@Qualifier("guitar")
private Instrument instrument;
使用@Qualifier意味着把@Autowired的byType自动转换为byName。
创建自动一的限定器(Qualifier)
本文不做讲解,可自行查阅《Spring 实战》
借助@Inject实现基于标准的自动装配
@Inject属于Java依赖注入规范,与@Autowired的不同是:@Inject没有required属性。
本文不做讲解,可自行查阅《Spring 实战》