Spring IoC的依赖注入过程,也就是从容器中找到依赖对象、注入到以后对象的过程,叫拆卸。
咱们后面看到的通过xml文件的<constructor-arg>和 <property> 中的 ref设置依赖对象的形式,是手动拆卸,因为每一个依赖对象都须要咱们手动配置、通过ref指定须要拆卸的具体bean,而后Spring依据咱们的指定来实现拆卸。拆卸好的残缺对象最终能力放入Spring IoC容器中供后续应用。
这种形式其实也比较简单实用 —在类比拟少、依赖关系比较简单的状况下。如果类比拟多、依赖关系比较复杂的话,配置起来就很烦很啰嗦。
为了解决这个问题,Spring提供了主动拆卸性能。主动拆卸的意思就是,Spring依据某种拆卸规定主动实现拆卸,不再须要咱们手工配置了。
主动拆卸可能防止臃肿的配置文件,进步开发效率。
主动拆卸应用起来也十分不便。还是应用咱们后面的例子:
<bean id="dependencyB" class="springTest.DependencyB" autowire="byName">
</bean>
<bean id="dependencyA" class="springTest.DependencyA">
</bean>
不须要为DependencyB设置指向dependencyA的ref,减少autowire=byname的配置,Spring主动就能够实现拆卸。
应用xml的启动类:
public class AppByXML {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("mySpring.xml");
System.out.println("Now start to getbean...");
DependencyB dependencyB = applicationContext.getBean(DependencyB.class);
dependencyB.testB();
}
}
执行启动类:
here you call set method...
Now start to getbean...
This is DependencyB's test and ...I am DependencyA test...
配置文件中并没有指定ref,Spring能够主动依照规定实现拆卸。
主动拆卸规定
Spring提供如下4种主动拆卸规定:
- no: 不执行主动拆卸。这个时候只能手动拆卸了。
- byName: 依据属性名实现主动拆卸。Spring依据以后属性的名字,查找容器中id或name等于该名字的Bean进行拆卸。找不到则不拆卸。
- byType: 依据属性的类型实现拆卸。Spring Ioc容器中该类型的Bean多于一个的话,抛异样。
- constructor: 相似byType,只不过是用在构造方法参数中,为构造方法的参数进行拆卸。
上例中咱们如果把拆卸规定批改为byType:
<bean id="dependencyB" class="springTest.DependencyB" autowire="byType">
</bean>
<bean id="dependencyA" class="springTest.DependencyA">
</bean>
执行启动类:
here you call set method...
Now start to getbean...
This is DependencyB's test and ...I am DependencyA test...
主动拆卸胜利。
然而如果咱们批改配置,再退出一个dependencyA之后:
<bean id="dependencyB" class="springTest.DependencyB" autowire="byType">
</bean>
<bean id="dependencyA" class="springTest.DependencyA">
</bean>
<bean id="dependencyA1" class="springTest.DependencyA">
</bean>
再次执行启动类:
抛出异样UnsatisfiedDependencyException...
expected single matching bean but found 2: dependencyA,dependencyA1
所以byType的状况下,Spring IoC容器中只能有一个该类型的Bean存在,多于一个则抛异样。
主动拆卸的益处和弊病
主动拆卸的益处就是能够简化配置,瘦身臃肿的配置文件,在设计变动后,比方减少或缩小依赖关系的时候不须要执行繁琐的配置文件同步批改工作,极大进步开发人员的效率。
然而主动拆卸也还是存在一些弊病或应用限度,包含:主动拆卸优先级低于手动拆卸,也不能对根底数据类型、Strings、Arrays等执行主动拆卸。以byType进行拆卸的时候,如果容器中存在多个该类型的Bean则会抛出异样等等。
然而这些弊病和限度其实是能够无效防止的,根底数据类型只能通过手动的形式进行拆卸,而且理论我的项目开发过程中须要拆卸根底数据类型的场景应该非常少。对于同一个类型存在多个Bean的状况,咱们其实在理论利用中应该尽可能通过设置primary或qulifier指定在拆卸过程中优先拆卸哪一个Bean,比方下面那个例子:
<bean id="dependencyB" class="springTest.DependencyB" autowire="byType">
</bean>
<bean id="dependencyA" class="springTest.DependencyA">
</bean>
<bean id="dependencyA1" primary="true" class="springTest.DependencyA">
</bean>
指定primary之后就没有问题了,最终dependencyA1会拆卸到DependencyB中。
所有我的项目中其实还是优先应用主动拆卸,因为益处显著多于弊病。
通过注解实现主动拆卸
@Autowired注解实现主动拆卸,能够作用在属性、办法、结构器上。
作用在属性上实现对该属性的主动拆卸,作用在结构器上、办法上,可主动拆卸结构器或办法参数。
@Autowired主动拆卸规定:(源码地位DefaultListableBeanFactory#doResolveDependency)
首先按类型(byType)匹配,匹配过程中会解决@Quarlifier:查看有@Quarlifier设置并且有匹配的Bean则返回,否则如果设置了@Quarlifier然而没有匹配的Bean则抛异样。
匹配后有以下几种状况:
- 没匹配到:@Autowired注解的参数required设置为true(默认为true)则抛异样,否则返回null
- 只匹配到一个Bean:间接注入
-
匹配到多个:须要进一步判断:
优先查看@Primary的Bean。没有@Primary则查看优先级的设置,返回最高优先级的Bean。
最初查看如果有与以后属性名称匹配的Bean则返回,没有的话就表明无奈胜利注入,依据required的设置抛异样(如果设置为true)或者返回null(如果设置为true)。
@Qulifier注解针对属性设置:
@Component
public class DependencyB implements IDependencyB{
@Autowired
@Qualifier(value="dependencyA")
private IDependencyA d;
@Primary注解则针对Bean设置,同类型的Bean只有一个能够设置为@Primary,否则在DI过程中会报错:
@Service
@Primary
public class DependencyA implements IDependencyA {
@Override
public void test(){
System.out.println("I am DependencyA test...");
}
}
上一篇 Spring FrameWork从入门到NB – Bean
发表回复