转载自 《Spring技术内幕》

在前面对IoC容器实现原理的分析中,一直是通过BeanDefinition的属性值和构造函数以显式的方式实现 Bean 的依赖关系管理的。在 Spring中,相对这种显式的依赖管理方式,IoC 容器还提供了自动依赖装配的方式,为应用使用容器提供更大的方便。在自动装配中,不需要对 Bean属性做显式的依赖关系声明,只需要配置好 autowire(自动依赖装配)属性,IoC 容器会根据这个属性的配置,使用反射自动地查找属性的类型或名字,然后基于属性的类型或名字来自动匹配IoC容器中的Bean,从而自动地完成依赖注入。

这是一个很有诱惑力的功能特性,使用它可以完成依赖关系管理的自动化,但是使用时一定要注意,计算机只是在自动地执行,它是不会思考的。使用这个特性的优点是能够减少用户配置Bean 的工作量,但如果使用不当,也会为应用带来不可预见的后果,就像我们使用其他方式的自动化一样。所以,使用起来需要多一些小心和谨慎。

从autowiring使用上可以知道,这个autowiring属性是在对Bean属性进行依赖注入时起作用的。对 Bean 属性依赖注入的实现原理,我们在前面已经做过分析。回顾那部分的内容,我们不难发现,对 autowirng 属性的处理,从而完成对 Bean 的属性的自动依赖装配。节选AbstractAutowireCapableBeanFactory的populateBean方法中与autowiring实现相关的部分,我们可以清楚地看到这个特性在容器中实现的入口。也就是说,对属性 autowire 的处理是populateBean处理过程的一个部分在populateBean的实现中,在处理一般的Bean之前,先对 autowiring 属性进行处理。如果当前的 Bean 配置了 autowire_by_name 和autowire_by_type 属性,那么调用相应的 autowireByName 方法和 autowireByType 方法。这两个方法很巧妙地应用了 IoC 容器的特性。例如,对于 autowire_by_name,它首先通过反射机制从当前 Bean 中得到需要注入的属性名,然后使用这个属性名向容器去申请与之同名的Bean,这样实际又触发了另一个Bean的生成和依赖注入的过程。实现过程如代码清单2-35所示。

代码清单2-35  populateBean对autowire的处理:
	//开始进行依赖注入过程,先处理autowire的注入。 
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||    
	mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {   
	MutablePropertyValues newPvs = new MutablePropertyValues(pvs);  
    // Add property values based on autowire by name if applicable.  
    //这里是对autowire注入的处理,根据bean的名字或者type进行autowire的过程。  
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {    
	    autowireByName(beanName, mbd, bw, newPvs);  
    }  
    //Add property values based on autowire by type if applicable.  
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {    
        autowireByType(beanName, mbd, bw, newPvs);  
    }  
    pvs = newPvs;  
} 
        在做了一些简单的对 autowiring 类型的逻辑判断以后,通过调用 autowireByName 和autowireByType 来完成自动依赖装配。以 autowireByName 为例来看看容器的自动依赖装配功能是怎样实现的;对 autowireByName 来说,它首先需要得到当前 Bean 的属性名,这些属性名已经在BeanWrapper和BeanDefinition中封装好了,然后就是对着一系列属性名进行匹配的过程。在这个匹配的过程中,因为已经有了属性的名字,那就可以直接使用这个属性名字作为Bean名字向容器getBean,这个getBean会触发当前Bean的依赖Bean的依赖注入的过程;从而得到属性对应的依赖Bean。在这个getBean完成后,把这个依赖Bean注入到当前Bean的属性中去;这样就完成了这个依赖属性名自动完成依赖注入的过程。对 autowireByType 的实现,和 autowireByName 的实现过程是非常类似的,感兴趣的读者可以自己进行分析。
        
按类型注入和按名称注入的简单介绍:

按类型注入域属性@Autowired

需要在域属性上使用注解@Autowired,该注解默认使用按类型自动装配Bean的方式。
使用该注解完成属性注入时,类中无需setter。当然,若属性有setter,则也可将其加到setter上。

按名称注入域属性@Autowired与@Qualifier

需要在域属性上联合使用注解@Autowired与@Qualifier。@Qualifier的value属性用于指定要匹配的Bean的id值。同样类中无需setter,也可加到setter上。

  

@Autowired还有一个属性required,默认值为true,表示当匹配失败后,会终止程序运行。若将其值设置为false,则匹配失败,将被忽略,未匹配的属性值为null。