它首先会尝试使用constructor进行自动装配如果失败再尝试使用byType。不过它在Spring3.0之后已经被标记为@Deprecated
。
Spring自动装配的优点不言而喻但是事实上,在Spring XML配置文件里的自动装配并不推荐使用其中笔者认为最大的缺点在于不确定性。或者除非你对整个Spring应用中的所有Bean的情况了如指掌不然随着Bean的增多和关系复杂度的上升,情况鈳能会很糟糕
从Spring2.5开始,开始支持使用注解来自动装配Bean的属性它允许更细粒度的自动装配,我们可以选择性的标注某一个属性来对其应鼡自动装配
Spring支持几种不同的应用于自动装配的注解。
我们今天只重点关注Autowired注解关于它的解析和注入过程,请参考笔者Spring源码系列的文章
使用@Autowired很简单,在需要注入的属性加入注解即可
不过,使用它有几个点需要注意
默认情况下,它具有强制契约特性其所标注的属性必须是可装配的。如果没有Bean可以装配到Autowired所标注的属性或参数中那么你会看到NoSuchBeanDefinitionException
的异常信息。
看到仩面的源码,我们可以得到这一信息Bean集合为空不要紧,关键isRequired
条件不能成立那么,如果我们不确定属性是否可以装配可以这样来使用Autowired。
我记得曾经有个面试题是这样问的:Autowired是按照什么策略来自动装配的呢
关于这个问题,不能一概而论你不能简单的说按照类型或者按照名称。但可以确定的一点的是它默认是按照类型来自动装配的,即byType
//获取给定类型的所有bean名称,里面实际循环所有的beanName获取它的实例 //根据返回的beanName,获取其实例返回
可以看到它返回的是一个列表那么就表明,按照类型匹配可能会查询到多个实例到底应该装配哪个实例呢?我看有的文章里说可以加注解以此规避。比如@qulifier、@Primary
等实际还有个简单的办法。
比如按照UserService接口类型来装配它的实现类。UserService接口有多个實现类分为UserServiceImpl、UserServiceImpl2
。那么我们在注入的时候就可以把属性名称定义为Bean实现类的名称。
这样的话Spring会按照byName来进行装配。首先如果查到类型嘚多个实例,Spring已经做了判断
//按照类型查找Bean实例 //如果查找的Bean实例大于1个 //找到最合适的那个,如果没有合适的。也抛出异常
可以看出如果查到多个实例,determineAutowireCandidate
方法就是关键它来确定一个合适的Bean返回。其中一部分就是按照Bean的名称来匹配
最后我们回到问题上,得到的答案就是:@Autowired默认使用byType来装配属性如果匹配到类型的多个实例,再通过byName来确定Bean
上面我们已经看到了,通过byType可能会找到多个实例的Bean然后再通过byName来确定一个合适的Bean,如果通过名称也确定不了呢
你也可以在Bean上配置@Priority注解,它有个int类型的属性value可以配置优先级大小。数字越小的就被优先匹配。同样的你也不能把多个Bean的优先级配置成相同大小的数值,否则NoUniqueBeanDefinitionException
异常照样出来找你
本章节重点阐述了Spring中的自动装配的几种策略,又通过源码分析了Autowired注解的使用方式