spring源码分析-IOC容器的高级特性

1.介绍
2.spring IOC容器的lzay-init属性实现预实例化
3.FactoryBean的实现
4.BeanPostProcessor后置处理的实现

5.Spring IOC容器autowiring实现原理


1.介绍
IOC容器除了对Bean的初始化和依赖注入之外还有一些高级特性,如使用lazy-init属性对Bean预初始化,FactoryBean产生或者修饰Bean对象的生成,IOC容器初始化Bean过程中使用BeanPostProcessor后置处理器对Bean声明周期事件管理和IOC容器的autowiring自动装配等

2.spring IOC容器的lzay-init属性实现预实例化
通过前面我们对IOC容器的实现和工作原理分析,我们知道IOC容器的初始化过程就是对Bean定义
资源的定位、载入和注册,此时容器对Bean的依赖注入并没有发生,依赖注入主要是在应用程序第一
次向容器索取Bean时,通过getBean方法的调用完成

当Bean定义资源的元素中配罝了lazx-init厲性时,容器将会在初始化的时候对所配置的Bean
进行预实例化,Bean的依赖注入在容器初候就已经完成。这样,当应用程序第一次向容器索取
被管理的Bean时,就不用再初始化和对Bean迸行依赖注入了.直接从容器中获取己经完成依赖注入的
现成Bean,可以提窩应用第一次向容器获取Bean的性能。

下面我们通过代码分析容器预实例化的实现过程:
(1)AbstractApplicationContext类的refresh方法
(2)finishBeanFactoryInitializatio进行预初始化Bean
(3)DefaultListableBeanFactory的preInstantiateSingletons对配置lazy-init属性Bean的预实例化

3.FactoryBean的实现
在Spring中,有两个很容易混滑的类:BeanFactory和FactoryBean
BeanFactory:Bean工厂,是一个工厂(Factory),我们SpringIOC容器的最顶层接口就是这个BeanFactory,它的作用是管理Bean,即实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

FactoryBean:工厂Bean,是一个Bean,作用是产生其他bean实例。通常情况下,这种bean没有什么仅需要提供一个工厂方法,该方法用来返回其他bean实例。通常情况下,bean无须自己实现工厂模式,Spring容器担任工厂角色;但少数情况下,容器中的bean本身就是工厂,其作用是产生其它bean实例。
当用户使用容器本身时,可以使用转义字符 & 来得到FactoryBean本身,以区别通过FactoryBean产生的实例对象和FactoryBean对象本身,在BeanFactory中通过如下代码定义了该转义字符:
String FACTORY_BEAN_PREFIX="&";
如果myJndiObject是一个FactoryBean,则使用&myJndiObject得到的是myJndiObject对象,而不是myJndiObject产生出来的对象。
(1)查看FactoryBean的源码

 1//工厂Bean,用于产生其他对象  
 2public interface FactoryBean<T{  
 3   //获取容器管理的对象实例  
 4    getObject() throws Exception;  
 5    //获取Bean工厂创建的对象的类型  
 6    Class<?> getObjectType();  
 7    //Bean工厂创建的对象是否是单态模式,如果是单态模式,则整个容器中只有一个实例  
 8   //对象,每次请求都返回同一个实例对象  
 9    boolean isSingleton();  
10}

(2)AbstractBeanFactory的getBean方法调用FactoryBean:
在前面我们分析Spring IOC容器实例化Bean并进行依赖注入过程的源码时,提到在getBean方法触发容器实例化Bean的时候会调用AbstractBeanFactory的doGetBean方法来进行实例化过程,查看源码:

 1//真正实现向IoC容器获取Bean的功能,也是触发依赖注入功能的地方    
 2     @SuppressWarnings("unchecked")    
 3     protected <T> doGetBean(    
 4             final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)    
 5             throws BeansException {    
 6         //根据指定的名称获取被管理Bean的名称,剥离指定名称中对容器的相关依赖    
 7         //如果指定的是别名,将别名转换为规范的Bean名称    
 8         final String beanName = transformedBeanName(name);    
 9         Object bean;    
10       //先从缓存中取是否已经有被创建过的单态类型的Bean,对于单态模式的Bean整    
11           //个IoC容器中只创建一次,不需要重复创建    
12         Object sharedInstance = getSingleton(beanName);    
13         //IoC容器创建单态模式Bean实例对象    
14         if (sharedInstance != null && args == null) {    
15             if (logger.isDebugEnabled()) {    
16             //如果指定名称的Bean在容器中已有单态模式的Bean被创建,直接返回    
17                   //已经创建的Bean    
18                 if (isSingletonCurrentlyInCreation(beanName)) {    
19                     logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +    
20                             "' that is not fully initialized yet - a consequence of a circular reference");    
21                 }    
22                 else {    
23                     logger.debug("Returning cached instance of singleton bean '" + beanName + "'");    
24                 }    
25             }    
26             //获取给定Bean的实例对象,主要是完成FactoryBean的相关处理   
27             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);    
28         }    
29        ……  
30    }  
31   //获取给定Bean的实例对象,主要是完成FactoryBean的相关处理 
32   protected Object getObjectForBeanInstance(  
33           Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {  
34       //容器已经得到了Bean实例对象,这个实例对象可能是一个普通的Bean,也可能是  
35       //一个工厂Bean,如果是一个工厂Bean,则使用它创建一个Bean实例对象,如果  
36       //调用本身就想获得一个容器的引用,则指定返回这个工厂Bean实例对象  
37       //如果指定的名称是容器的解引用(dereference,即是对象本身而非内存地址),  
38       //且Bean实例也不是创建Bean实例对象的工厂Bean  
39       if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {  
40           throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());  
41       }  
42       //如果Bean实例不是工厂Bean,或者指定名称是容器的解引用,调用者向获取对  
43       //容器的引用,则直接返回当前的Bean实例  
44       if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {  
45           return beanInstance;  
46       }  
47   //处理指定名称不是容器的解引用,或者根据名称获取的Bean实例对象是一个工厂Bean  
48   //使用工厂Bean创建一个Bean的实例对象  
49       Object object = null;  
50       if (mbd == null) {  
51           //从Bean工厂缓存中获取给定名称的Bean实例对象  
52           object = getCachedObjectForFactoryBean(beanName);  
53       }  
54       //让Bean工厂生产给定名称的Bean对象实例  
55       if (object == null) {  
56           FactoryBean factory = (FactoryBean) beanInstance;  
57           //如果从Bean工厂生产的Bean是单态模式的,则缓存  
58           if (mbd == null && containsBeanDefinition(beanName)) {  
59               //从容器中获取指定名称的Bean定义,如果继承基类,则合并基类相关属性  
60               mbd = getMergedLocalBeanDefinition(beanName);  
61           }  
62           //如果从容器得到Bean定义信息,并且Bean定义信息不是虚构的,则让工厂  
63           //Bean生产Bean实例对象  
64           boolean synthetic = (mbd != null && mbd.isSynthetic());  
65           //调用FactoryBeanRegistrySupport类的getObjectFromFactoryBean  
66           //方法,实现工厂Bean生产Bean对象实例的过程  
67           object = getObjectFromFactoryBean(factory, beanName, !synthetic);  
68       }  
69       return object;  
70    }

在上面获取给定Bean的实例对象的getObjectForBeanInstance方法中,会调用FactoryBeanRegisterSupport类的getObjectFromFactoryBean方法,该方法实现了Bean工厂生产Bean实例对象。

Dereference(解引用):一个在C/C++中应用比较多的术语,在C++中,“* ”是解引用符号,而 & 是引用符号,解引用是指变量指向的是所引用对象的本身数据,而不是引用对象的内存地址。

(3)AbstractBeanFactory生产Bean实例对象
AbstractBeanFactory类中生产Bean实例对象的主要源码如下:

 1//Bean工厂生产Bean实例对象  
 2   protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {  
 3       //Bean工厂是单态模式,并且Bean工厂缓存中存在指定名称的Bean实例对象  
 4       if (factory.isSingleton() && containsSingleton(beanName)) {  
 5           //多线程同步,以防止数据不一致  
 6           synchronized (getSingletonMutex()) {  
 7               //直接从Bean工厂缓存中获取指定名称的Bean实例对象  
 8               Object object = this.factoryBeanObjectCache.get(beanName);  
 9               //Bean工厂缓存中没有指定名称的实例对象,则生产该实例对象  
10               if (object == null) {  
11                   //调用Bean工厂的getObject方法生产指定Bean的实例对象  
12                   object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);  
13                   //将生产的实例对象添加到Bean工厂缓存中  
14                   this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));  
15               }  
16               return (object != NULL_OBJECT ? object : null);  
17           }  
18       }  
19       //调用Bean工厂的getObject方法生产指定Bean的实例对象  
20       else {  
21           return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);  
22       }  
23   }  
24   //调用Bean工厂的getObject方法生产指定Bean的实例对象  
25   private Object doGetObjectFromFactoryBean(  
26           final FactoryBean factory, final String beanName, final boolean shouldPostProcess)  
27           throws BeanCreationException {  
28       Object object;  
29       try {  
30           if (System.getSecurityManager() != null) {  
31               AccessControlContext acc = getAccessControlContext();  
32               try {  
33                   //实现PrivilegedExceptionAction接口的匿名内置类  
34                   //根据JVM检查权限,然后决定BeanFactory创建实例对象  
35                   object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {  
36                       public Object run() throws Exception {  
37                               //调用BeanFactory接口实现类的创建对象方法  
38                               return factory.getObject();  
39                           }  
40                       }, acc);  
41               }  
42               catch (PrivilegedActionException pae) {  
43                   throw pae.getException();  
44               }  
45           }  
46           else {  
47               //调用BeanFactory接口实现类的创建对象方法  
48               object = factory.getObject();  
49           }  
50       }  
51       catch (FactoryBeanNotInitializedException ex) {  
52           throw new BeanCurrentlyInCreationException(beanName, ex.toString());  
53       }  
54       catch (Throwable ex) {  
55           throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);  
56       }  
57       //创建出来的实例对象为null,或者因为单态对象正在创建而返回null  
58       if (object == null && isSingletonCurrentlyInCreation(beanName)) {  
59           throw new BeanCurrentlyInCreationException(  
60                   beanName, "FactoryBean which is currently in creation returned null from getObject");  
61       }  
62       //为创建出来的Bean实例对象添加BeanPostProcessor后置处理器  
63       if (object != null && shouldPostProcess) {  
64           try {  
65               object = postProcessObjectFromFactoryBean(object, beanName);  
66           }  
67           catch (Throwable ex) {  
68               throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);  
69           }  
70       }  
71       return object;  
72    }

从上面的源码分析中,我们可以看出,BeanFactory接口调用其实现类的getObject方法来实现创建Bean实例对象的功能。

(4)工厂Bean的实现类getObject方法创建Bean实例对象:
FactoryBean的实现类有非常多,比如Proxy,RMI,JNDI,ServletContextFactoryBean等待,FactoryBean接口为Spring容器提供了一个很好的封装机制,具体的getObject有不同的实现类根据不同的实现策略来具体提供,我们分析一个最简单的AnnotationTestFactoryBean的实现源码

 1public class AnnotationTestBeanFactory implements FactoryBean<IJmxTestBean{  
 2       private final FactoryCreatedAnnotationTestBean instance = new FactoryCreatedAnnotationTestBean();  
 3       public AnnotationTestBeanFactory() {  
 4           this.instance.setName("FACTORY");  
 5       }  
 6       //AnnotationTestBeanFactory产生Bean实例对象的实现  
 7       public IJmxTestBean getObject() throws Exception {  
 8           return this.instance;  
 9       }  
10       public Class<? extends IJmxTestBean> getObjectType() {  
11           return FactoryCreatedAnnotationTestBean.class;  
12       }  
13       public boolean isSingleton() {  
14           return true;  
15       }  
16     }

其他的Proxy,RMI,JNDI等都市根据相应的策略提供getObject的实现,这里不做一一分析,这已经不是Spring的核心功能

4.BeanPostProcessor后置处理的实现
BeanPostProcessor后置处理器是SPring IOC容器经常使用到的一个特性,这个Bean后置处理器是一个监听器,可以监听容器触发的Bean声明周期事件,后置处理器向容器注册以后,容器中管理的Bean就具备了接受IOC容器事件的回调的能力

BeanPostProcessor的使用非常讲的,只需要提供一个实现接口BeanPostProcessor的实现类,然后在Bean的配置文件中设置即可。
(1)BeanPostProcessor的源码查看

1package org.springframework.beans.factory.config;  
2   import org.springframework.beans.BeansException;  
3   public interface BeanPostProcessor {  
4       //为在Bean的初始化前提供回调入口  
5       Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;  
6       //为在Bean的初始化之后提供回调入口  
7       Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;  
8     }

这两个回调的入口都是和容器管理的Bean的生命周期事件紧密相关,可以为用户提供在SpringIOC
容器初始化Bean过程中自定义的处理操作。

(2)AbstractAutowireCapableBeanFactory类对容器生成的Bean添加后置处理器:

BeanPostProcessor后罝处理器的调用发生在SpringIOC容器完成对Bean实例对象的创建和属性的依赖注入完成之后,在对spring的源码分析过程中我们知道,当应用程序第一次调用getBean方法(lazy-init;预实例化除外)向SpringI0C容器索取指定Bean时触发SpringI0C容器创建Bean实例对象并进行依赖注入的过程,其中真正实现创建Bean对象并进行依赖注入的方法是AbstractAutowireCapableBeanFactory类的doCreateBean方法,主要源码如下:

 1//真正创建Bean的方法  
 2   protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {  
 3       //创建Bean实例对象  
 4       ……  
 5       try {  
 6           //对Bean属性进行依赖注入  
 7           populateBean(beanName, mbd, instanceWrapper);  
 8           if (exposedObject != null) {  
 9               //在对Bean实例对象生成和依赖注入完成以后,开始对Bean实例对象  
10              //进行初始化 ,为Bean实例对象应用BeanPostProcessor后置处理器  
11              exposedObject = initializeBean(beanName, exposedObject, mbd);  
12           }  
13       }  
14       catch (Throwable ex) {  
15           if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {  
16               throw (BeanCreationException) ex;  
17           }  
18       ……  
19       //为应用返回所需要的实例对象  
20       return exposedObject;  
21    }

分析代码我们知道,为Bean实例对象添加BeanPostProcessor后置处理器的入口initializeBean方法

(3)initializeBean方法为容器产生的Bean实例对象添加BeanPostProcessor后置处理器:
同样在AbstractAutowireCapableBeanFactory类中,initializeBean方法实现为容器创建的Bean实例对象添加BeanPostProcessor后置处理器,源码查看

 1//初始容器创建的Bean实例对象,为其添加BeanPostProcessor后置处理器  
 2   protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {  
 3       //JDK的安全机制验证权限  
 4       if (System.getSecurityManager() != null) {  
 5           //实现PrivilegedAction接口的匿名内部类  
 6           AccessController.doPrivileged(new PrivilegedAction<Object>() {  
 7               public Object run() {  
 8                   invokeAwareMethods(beanName, bean);  
 9                   return null;  
10               }  
11           }, getAccessControlContext());  
12       }  
13       else {  
14           //为Bean实例对象包装相关属性,如名称,类加载器,所属容器等信息  
15           invokeAwareMethods(beanName, bean);  
16       }  
17       Object wrappedBean = bean;  
18       //对BeanPostProcessor后置处理器的postProcessBeforeInitialization  
19       //回调方法的调用,为Bean实例初始化前做一些处理  
20       if (mbd == null || !mbd.isSynthetic()) {  
21           wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);  
22       }  
23       //调用Bean实例对象初始化的方法,这个初始化方法是在Spring Bean定义配置  
24       //文件中通过init-method属性指定的  
25       try {  
26           invokeInitMethods(beanName, wrappedBean, mbd);  
27       }  
28       catch (Throwable ex) {  
29           throw new BeanCreationException(  
30                   (mbd != null ? mbd.getResourceDescription() : null),  
31                   beanName, "Invocation of init method failed", ex);  
32       }  
33       //对BeanPostProcessor后置处理器的postProcessAfterInitialization  
34       //回调方法的调用,为Bean实例初始化之后做一些处理  
35       if (mbd == null || !mbd.isSynthetic()) {  
36           wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);  
37       }  
38       return wrappedBean;  
39   }  
40   //调用BeanPostProcessor后置处理器实例对象初始化之前的处理方法  
41   public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)  
42           throws BeansException {  
43       Object result = existingBean;  
44       //遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器  
45       for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {  
46           //调用Bean实例所有的后置处理中的初始化前处理方法,为Bean实例对象在  
47           //初始化之前做一些自定义的处理操作  
48           result = beanProcessor.postProcessBeforeInitialization(result, beanName);  
49           if (result == null) {  
50               return result;  
51           }  
52       }  
53       return result;  
54   }  
55   //调用BeanPostProcessor后置处理器实例对象初始化之后的处理方法  
56   public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)  
57           throws BeansException {  
58       Object result = existingBean;  
59       //遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器  
60       for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {  
61           //调用Bean实例所有的后置处理中的初始化后处理方法,为Bean实例对象在  
62           //初始化之后做一些自定义的处理操作  
63           result = beanProcessor.postProcessAfterInitialization(result, beanName);  
64           if (result == null) {  
65               return result;  
66           }  
67       }  
68       return result;  
69    }

BeanPostProcessor是一个接口,其初始化前的操作方法和初始化后的操作方法均委托其实现子类;来实现,在Spring中,BeanPostProcessor的实现子类非常的多,分别完成不同的操作,如AOP面向切面编程的注册通知适配器,Bean对象的数据校验,Bean继承属性/方法的合并等等,我们以最简单的AOP切面织入来简单了解其主要的功能。

(4)AdvisorAdaperRegistrationManager在Bean对象初始化后注册通知适配器:
AdvisorAdaperRegistrationManager是BeanPostProcessor的一个实现类,其主要的作用为容器中管理的Bean注册一个面向切面编程的通知适配器,以便在spring容器为所管理的Bean进行面向切面编程时提供方便,源码查看

 1//为容器中管理的Bean注册一个面向切面编程的通知适配器  
 2public class AdvisorAdapterRegistrationManager implements BeanPostProcessor {  
 3   //容器中负责管理切面通知适配器注册的对象  
 4   private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();  
 5   public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {  
 6       this.advisorAdapterRegistry = advisorAdapterRegistry;  
 7   }  
 8   //BeanPostProcessor在Bean对象初始化前的操作  
 9   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
10       //没有做任何操作,直接返回容器创建的Bean对象  
11       return bean;  
12   }  
13   //BeanPostProcessor在Bean对象初始化后的操作  
14   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
15       if (bean instanceof AdvisorAdapter){  
16           //如果容器创建的Bean实例对象是一个切面通知适配器,则向容器的注册
17              this.advisorAdapterRegistry.registerAdvisorAdapter((AdvisorAdapter) bean);  
18       }  
19       return bean;  
20   }  
21}

其他的BeanPostProcessor接口实现类也类似,都是对Bean对象使用到的一些特性进行处理,或者向IOC容器中注册,为创建的Bean实例对象做一些自定义的功能增加,这些操作是容器初始化Bean时自动触发的,不需要认为的干预

5.Spring IOC容器autowiring实现原理
spring IOC容器提供了两种管理Bean依赖关系的方式:
a.显示管理:通过BeanDefinition的属性值和构造方法实现Bean依赖关系管理。
b.autowiring :spring IOC容器依赖自动装配功能,不需要对Bean属性的依赖管理做显式声明,只需要在配置好autowiring属性,IOC容器会自动使用反射查找属性的类型和名称,然后基于属性的类型或者名称来自动匹配容器中管理的Bean,从而自动地完成依赖注入。

通过autowiring自动装配特性的理解,我们知道容器对Bean的自动装配发生在容器对Bean依赖注入的过程中,在前面对SPring IOC容器的依赖注入过程源码分析中,我们已经知道了容器对Bean实例对象的属性注入的处理发生在AbstractAutowireCapableBeanFactory类中的populateBean方法中,我们通过程序流程分析autowiring的实现原理:
(1)AbstractAutowireCapableBeanFactory对Bean实例进行属性依赖注入:
应用第一次通过getBean方法向IOC容器索取Bean时,容器创建Bean实例对象,并且对Bean实例对象进行属性依赖注入,AbstractAutowireCapableBeanFactory的populateBean方法就是实现Bean属性依赖注入的功能,源码查看

 1protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {  
 2       //获取Bean定义的属性值,并对属性值进行处理  
 3       PropertyValues pvs = mbd.getPropertyValues();  
 4       ……  
 5       //对依赖注入处理,首先处理autowiring自动装配的依赖注入  
 6       if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||  
 7               mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
 8           MutablePropertyValues newPvs = new MutablePropertyValues(pvs);  
 9           //根据Bean名称进行autowiring自动装配处理  
10           if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {  
11               autowireByName(beanName, mbd, bw, newPvs);  
12           }  
13           //根据Bean类型进行autowiring自动装配处理  
14           if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
15               autowireByType(beanName, mbd, bw, newPvs);  
16           }  
17       }  
18       //对非autowiring的属性进行依赖注入处理  
19        ……  
20    }

(2)spring IOC容器根据Bean名称或者类型进行autowiring自动依赖注入:

 1//根据名称对属性进行自动依赖注入  
 2   protected void autowireByName(  
 3           String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {  
 4        //对Bean对象中非简单属性(不是简单继承的对象,如8中原始类型,字符串,URL等//都是简单属性)进行处理  
 5       String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);  
 6       for (String propertyName : propertyNames) {  
 7           //如果Spring IoC容器中包含指定名称的Bean  
 8           if (containsBean(propertyName)) {  
 9                //调用getBean方法向IoC容器索取指定名称的Bean实例,迭代触发属性的//初始化和依赖注入  
10               Object bean = getBean(propertyName);  
11               //为指定名称的属性赋予属性值  
12               pvs.add(propertyName, bean);  
13               //指定名称属性注册依赖Bean名称,进行属性依赖注入  
14               registerDependentBean(propertyName, beanName);  
15               if (logger.isDebugEnabled()) {  
16                   logger.debug("Added autowiring by name from bean name '" + beanName +  
17                           "' via property '" + propertyName + "' to bean named '" + propertyName + "'");  
18               }  
19           }  
20           else {  
21               if (logger.isTraceEnabled()) {  
22                   logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +  
23                           "' by name: no matching bean found");  
24               }  
25           }  
26       }  
27   }  
28   //根据类型对属性进行自动依赖注入  
29   protected void autowireByType(  
30           String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {  
31       //获取用户定义的类型转换器  
32       TypeConverter converter = getCustomTypeConverter();  
33       if (converter == null) {  
34           converter = bw;  
35       }  
36       //存放解析的要注入的属性  
37       Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);  
38         //对Bean对象中非简单属性(不是简单继承的对象,如8中原始类型,字符  
39        //URL等都是简单属性)进行处理  
40       String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);  
41       for (String propertyName : propertyNames) {  
42           try {  
43               //获取指定属性名称的属性描述器  
44               PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);  
45               //不对Object类型的属性进行autowiring自动依赖注入  
46               if (!Object.class.equals(pd.getPropertyType())) {  
47                   //获取属性的setter方法  
48                   MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);  
49                   //检查指定类型是否可以被转换为目标对象的类型  
50                   boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());  
51                   //创建一个要被注入的依赖描述  
52                   DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);  
53                   //根据容器的Bean定义解析依赖关系,返回所有要被注入的Bean对象  
54                   Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);  
55                   if (autowiredArgument != null) {  
56                       //为属性赋值所引用的对象  
57                       pvs.add(propertyName, autowiredArgument);  
58                   }  
59                   for (String autowiredBeanName : autowiredBeanNames) {  
60                       //指定名称属性注册依赖Bean名称,进行属性依赖注入  
61                       registerDependentBean(autowiredBeanName, beanName);  
62                       if (logger.isDebugEnabled()) {  
63                           logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +  
64                                   propertyName + "' to bean named '" + autowiredBeanName + "'");  
65                       }  
66                   }  
67                   //释放已自动注入的属性  
68                   autowiredBeanNames.clear();  
69               }  
70           }  
71           catch (BeansException ex) {  
72               throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);  
73           }  
74       }  
75    }

通过源码分析,我们可以看出来通过属性名进行自动依赖注入的相对比通过属性类型进行自动依赖注入的要稍微简单一些,但是真正实现属性注入的是DefaultSingletonBeanRegistry类的registerDependentBean方法
(3)DefaultSingletonBeanRegistry类的registerDependentBean方法对属性注入:

 1//为指定的Bean注入依赖的Bean  
 2   public void registerDependentBean(String beanName, String dependentBeanName) {  
 3       //处理Bean名称,将别名转换为规范的Bean名称  
 4       String canonicalName = canonicalName(beanName);  
 5       //多线程同步,保证容器内数据的一致性  
 6       //先从容器中:bean名称-->全部依赖Bean名称集合找查找给定名称Bean的依赖Bean  
 7       synchronized (this.dependentBeanMap) {  
 8           //获取给定名称Bean的所有依赖Bean名称  
 9           Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);  
10           if (dependentBeans == null) {  
11               //为Bean设置依赖Bean信息  
12               dependentBeans = new LinkedHashSet<String>(8);  
13               this.dependentBeanMap.put(canonicalName, dependentBeans);  
14           }  
15           //向容器中:bean名称-->全部依赖Bean名称集合添加Bean的依赖信息  
16           //即,将Bean所依赖的Bean添加到容器的集合中  
17           dependentBeans.add(dependentBeanName);  
18       }  
19         //从容器中:bean名称-->指定名称Bean的依赖Bean集合找查找给定名称  
20        //Bean的依赖Bean  
21       synchronized (this.dependenciesForBeanMap) {  
22           Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName);  
23           if (dependenciesForBean == null) {  
24               dependenciesForBean = new LinkedHashSet<String>(8);  
25               this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);  
26           }  
27           //向容器中:bean名称-->指定Bean的依赖Bean名称集合添加Bean的依赖信息  
28           //即,将Bean所依赖的Bean添加到容器的集合中  
29           dependenciesForBean.add(canonicalName);  
30       }  
31    }

通过对autowiring的源码分析,我们可以看出autowiring的实现过程:
a.对Bean的属性代调用getBean方法,完成依赖Bean的初始化和依赖注入。
b.将依赖Bean的属性引用设置到被依赖的Bean属性上。
c.将依赖Bean的名称和被依赖Bean的名称存储在IOC容器的集合中

Spring IOC容器的autowiring属性自动依赖注入是一个很方便的特性,可以简化开发时的配置,但是凡事都有两面性,自动属性依赖注入也有不足,首先,Bean的依赖关系在配置文件中无法很清楚地看出来,对于维护造成一定困难,其次,由于自动依赖注入是Spring容器自动执行的,容器是不会只能判断的,如果配置不当,将会带来无法预料的后果,所以自动依赖注入特性在使用是还是综合考虑。

猜你喜欢

转载自blog.csdn.net/charjay_lin/article/details/80961433