这是一个很有诱惑力的功能特性,使用它可以完成依赖关系管理的自动化,但是使用时一定要注意,计算机只是在自动地执行,它是不会思考的。使用这个特性的优点是能够减少用户配置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所示。
//开始进行依赖注入过程,先处理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。