Spring--IoC容器對非lazy-init的singleton Bean實例化過程

本文轉載自《http://blog.csdn.net/chjttony/article/details/6278627》,想總結Bean實例化過程,總結也是作筆記,有總結得很好的就“拿來主義”了。


下面我們通過代碼分析容器預實例化的實現過程:

(1).先從IoC容器的初始會過程開始,通過前面文章分析,我們知道IoC容器讀入已經定位的Bean定義資源是從refresh方法開始的,我們首先從AbstractApplicationContext類的refresh方法入手分析,源碼如下:

  1. //容器初始化的過程,讀入Bean定義資源,並解析註冊  
  2. public void refresh() throws BeansException, IllegalStateException {  
  3.         synchronized (this.startupShutdownMonitor) {  
  4.             //調用容器準備刷新的方法,獲取容器的當時時間,同時給容器設置同步標識  
  5.             prepareRefresh();  
  6.             //告訴子類啓動refreshBeanFactory()方法,Bean定義資源文件的載入從  
  7. //子類的refreshBeanFactory()方法啓動  
  8.             ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  
  9. //爲BeanFactory配置容器特性,例如類加載器、事件處理器等  
  10.             prepareBeanFactory(beanFactory);  
  11.             try {  
  12.                 //爲容器的某些子類指定特殊的BeanPost事件處理器  
  13.                 postProcessBeanFactory(beanFactory);  
  14.                 //調用所有註冊的BeanFactoryPostProcessor的Bean  
  15.                 invokeBeanFactoryPostProcessors(beanFactory);  
  16.                 //爲BeanFactory註冊BeanPost事件處理器.  
  17.                 //BeanPostProcessor是Bean後置處理器,用於監聽容器觸發的事件  
  18.                 registerBeanPostProcessors(beanFactory);  
  19.                 //初始化信息源,和國際化相關.  
  20.                 initMessageSource();  
  21.                 //初始化容器事件傳播器.  
  22.                 initApplicationEventMulticaster();  
  23.                 //調用子類的某些特殊Bean初始化方法  
  24.                 onRefresh();  
  25.                 //爲事件傳播器註冊事件監聽器.  
  26.                 registerListeners();  
  27.                 //這裏是對容器lazy-init屬性進行處理的入口方法  
  28.                 finishBeanFactoryInitialization(beanFactory);  
  29.                 //初始化容器的生命週期事件處理器,併發布容器的生命週期事件  
  30.                 finishRefresh();  
  31.             }  
  32.             catch (BeansException ex) {  
  33.                 //銷燬以創建的單態Bean  
  34.                 destroyBeans();  
  35. //取消refresh操作,重置容器的同步標識.  
  36.                 cancelRefresh(ex);  
  37.                 throw ex;  
  38.             }  
  39.         }  
  40.     }  

refresh方法中ConfigurableListableBeanFactorybeanFactory = obtainFreshBeanFactory();啓動了Bean定義資源的載入、註冊過程,而finishBeanFactoryInitialization方法是對註冊後的Bean定義中的預實例化(lazy-init=falseSpring默認就是預實例化,即爲true)Bean進行處理的地方。

(2).finishBeanFactoryInitialization處理預實例化Bean

Bean定義資源被載入IoC容器之後,容器將Bean定義資源解析爲容器內部的數據結構BeanDefinition註冊到容器中,AbstractApplicationContext類中的finishBeanFactoryInitialization方法對配置了預實例化屬性的Bean進行預初始化過程,源碼如下:

  1. //對配置了lazy-init屬性的Bean進行預實例化處理  
  2. protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {  
  3.         //這是Spring3以後新加的代碼,爲容器指定一個轉換服務(ConversionService)  
  4. //在對某些Bean屬性進行轉換時使用  
  5. if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&  
  6.                 beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {  
  7.             beanFactory.setConversionService(  
  8.                     beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));  
  9.         }  
  10.         //爲了類型匹配,停止使用臨時的類加載器  
  11.         beanFactory.setTempClassLoader(null);  
  12.         //緩存容器中所有註冊的BeanDefinition元數據,以防被修改  
  13.         beanFactory.freezeConfiguration();  
  14.         //對配置了lazy-init屬性的單態模式Bean進行預實例化處理  
  15.         beanFactory.preInstantiateSingletons();  
  16.     }  
  17. ConfigurableListableBeanFactory是一個接口,其preInstantiateSingletons方法由其子類DefaultListableBeanFactory提供。  
  18. (3).DefaultListableBeanFactory對配置lazy-init屬性單態Bean的預實例化:  
  19. //對配置lazy-init屬性單態Bean的預實例化  
  20. public void preInstantiateSingletons() throws BeansException {  
  21.         if (this.logger.isInfoEnabled()) {  
  22.             this.logger.info("Pre-instantiating singletons in " + this);  
  23.         }  
  24.         //在對配置lazy-init屬性單態Bean的預實例化過程中,必須多線程同步,以確  
  25. //保數據一致性  
  26.         synchronized (this.beanDefinitionMap) {  
  27.             for (String beanName : this.beanDefinitionNames) {  
  28.                 //獲取指定名稱的Bean定義  
  29.                 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);  
  30.                 //Bean不是抽象的,是單態模式的,且lazy-init屬性配置爲false  
  31.                 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {  
  32.                     //如果指定名稱的bean是創建容器的Bean  
  33.                     if (isFactoryBean(beanName)) {  
  34. //FACTORY_BEAN_PREFIX=”&”,當Bean名稱前面加”&”符號  
  35. //時,獲取的是產生容器對象本身,而不是容器產生的Bean.  
  36. //調用getBean方法,觸發容器對Bean實例化和依賴注入過程  
  37.                         final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);  
  38.                         //標識是否需要預實例化  
  39.                         boolean isEagerInit;  
  40.                         if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {  
  41.                             //一個匿名內部類  
  42.                             isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {  
  43.                                 public Boolean run() {  
  44.                                     return ((SmartFactoryBean) factory).isEagerInit();  
  45.                                 }  
  46.                             }, getAccessControlContext());  
  47.                         }  
  48.                         else {  
  49.                             isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit();   
  50.                         }  
  51.                         if (isEagerInit) {  
  52. //調用getBean方法,觸發容器對Bean實例化和依賴注入過程  
  53.                             getBean(beanName);  
  54.                         }  
  55.                     }  
  56.                     else {  
  57. //調用getBean方法,觸發容器對Bean實例化和依賴注入過程  
  58.                         getBean(beanName);  
  59.                     }  
  60.                 }  
  61.             }  
  62.         }  
  63.     }   

通過對lazy-init處理源碼的分析,我們可以看出,如果設置了lazy-init屬性,則容器在完成Bean定義的註冊之後,會通過getBean方法,觸發對指定Bean的初始化和依賴注入過程,這樣當應用第一次向容器索取所需的Bean時,容器不再需要對Bean進行初始化和依賴注入,直接從已經完成實例化和依賴注入的Bean中取一個線程的Bean,這樣就提高了第一次獲取Bean的性能。

3.FactoryBean的實現:

在Spring中,有兩個很容易混淆的類:BeanFactory和FactoryBean
BeanFactory:Bean工廠,是一個工廠(Factory),我們Spring IoC容器的最頂層接口就是這個BeanFactory,它的作用是管理Bean,即實例化、定位、配置應用程序中的對象及建立這些對象間的依賴。

FactoryBean:工廠Bean,是一個Bean,作用是產生其他bean實例。通常情況下,這種bean沒有什麼特別的要求,僅需要提供一個工廠方法,該方法用來返回其他bean實例。通常情況下,bean無須自己實現工廠模式,Spring容器擔任工廠角色;但少數情況下,容器中的bean本身就是工廠,其作用是產生其它bean實例。

當用戶使用容器本身時,可以使用轉義字符”&”來得到FactoryBean本身,以區別通過FactoryBean產生的實例對象和FactoryBean對象本身。在BeanFactory中通過如下代碼定義了該轉義字符:

StringFACTORY_BEAN_PREFIX = "&";

如果myJndiObject是一個FactoryBean,則使用&myJndiObject得到的是myJndiObject對象,而不是myJndiObject產生出來的對象。

(1).FactoryBean的源碼如下:

  1. //工廠Bean,用於產生其他對象  
  2. public interface FactoryBean<T> {  
  3. //獲取容器管理的對象實例  
  4.     T getObject() throws Exception;  
  5.     //獲取Bean工廠創建的對象的類型  
  6.     Class<?> getObjectType();  
  7.     //Bean工廠創建的對象是否是單態模式,如果是單態模式,則整個容器中只有一個實例  
  8. //對象,每次請求都返回同一個實例對象  
  9.     boolean isSingleton();  
  10. }  

(2). AbstractBeanFactory的getBean方法調用FactoryBean:

在第5篇博客我們分析Spring Ioc容器實例化Bean並進行依賴注入過程的源碼時,提到在getBean方法觸發容器實例化Bean的時候會調用AbstractBeanFactory的doGetBean方法來進行實例化的過程,源碼如下:

  1. //真正實現向IoC容器獲取Bean的功能,也是觸發依賴注入功能的地方    
  2.       @SuppressWarnings("unchecked")    
  3.       protected <T> 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的相關處理 protected Object getObjectForBeanInstance(  
  32.             Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {  
  33.         //容器已經得到了Bean實例對象,這個實例對象可能是一個普通的Bean,也可能是  
  34.         //一個工廠Bean,如果是一個工廠Bean,則使用它創建一個Bean實例對象,如果  
  35. //調用本身就想獲得一個容器的引用,則指定返回這個工廠Bean實例對象  
  36.         //如果指定的名稱是容器的解引用(dereference,即是對象本身而非內存地址),  
  37. //且Bean實例也不是創建Bean實例對象的工廠Bean  
  38.         if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {  
  39.             throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());  
  40.         }  
  41.         //如果Bean實例不是工廠Bean,或者指定名稱是容器的解引用,調用者向獲取對  
  42. //容器的引用,則直接返回當前的Bean實例  
  43.         if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {  
  44.             return beanInstance;  
  45.         }  
  46.     //處理指定名稱不是容器的解引用,或者根據名稱獲取的Bean實例對象是一個工廠Bean  
  47.     //使用工廠Bean創建一個Bean的實例對象  
  48.         Object object = null;  
  49.         if (mbd == null) {  
  50.             //從Bean工廠緩存中獲取給定名稱的Bean實例對象  
  51.             object = getCachedObjectForFactoryBean(beanName);  
  52.         }  
  53.         //讓Bean工廠生產給定名稱的Bean對象實例  
  54.         if (object == null) {  
  55.             FactoryBean factory = (FactoryBean) beanInstance;  
  56.             //如果從Bean工廠生產的Bean是單態模式的,則緩存  
  57.             if (mbd == null && containsBeanDefinition(beanName)) {  
  58.                 //從容器中獲取指定名稱的Bean定義,如果繼承基類,則合併基類相關屬性  
  59.                 mbd = getMergedLocalBeanDefinition(beanName);  
  60.             }  
  61.             //如果從容器得到Bean定義信息,並且Bean定義信息不是虛構的,則讓工廠  
  62.             //Bean生產Bean實例對象  
  63.             boolean synthetic = (mbd != null && mbd.isSynthetic());  
  64.             //調用FactoryBeanRegistrySupport類的getObjectFromFactoryBean  
  65.             //方法,實現工廠Bean生產Bean對象實例的過程  
  66.             object = getObjectFromFactoryBean(factory, beanName, !synthetic);  
  67.         }  
  68.         return object;  
  69.     }  

在上面獲取給定Bean的實例對象的getObjectForBeanInstance方法中,會調用FactoryBeanRegistrySupport類的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的實現類有非常多,比如:ProxyRMIJNDIServletContextFactoryBean等等,FactoryBean接口爲Spring容器提供了一個很好的封裝機制,具體的getObject有不同的實現類根據不同的實現策略來具體提供,我們分析一個最簡單的AnnotationTestFactoryBean的實現源碼:

  1. public 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. }  

其他的ProxyRMIJNDI等等,都是根據相應的策略提供getObject的實現。這裏不做一一分析,這已經不是Spring的核心功能,有需要的時候再去深入研究。

4.BeanPostProcessor後置處理器的實現:

BeanPostProcessor後置處理器是Spring IoC容器經常使用到的一個特性,這個Bean後置處理器是一個監聽器,可以監聽容器觸發的Bean聲明週期事件。後置處理器想容器註冊以後,容器中管理的Bean就具備了接收IoC容器事件回調的能力。

BeanPostProcessor的使用非常簡單,只需要提供一個實現接口BeanPostProcessor的實現類,然後在Bean的配置文件中設置即可。

(1).BeanPostProcessor的源碼如下:

  1. package 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的生命週期事件緊密相關,可以爲用戶提供在Spring IoC容器初始化Bean過程中自定義的處理操作。

(2).AbstractAutowireCapableBeanFactory類對容器生成的Bean添加後置處理器:

BeanPostProcessor後置處理器的調用發生在Spring IoC容器完成對Bean實例對象的創建和屬性的依賴注入完成之後,在對Spring依賴注入的源碼分析過程中我們知道,當應用程序第一次調用getBean方法(lazy-init預實例化除外)Spring IoC容器索取指定Bean時觸發Spring IoC容器創建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).AdvisorAdapterRegistrationManagerBean對象初始化後註冊通知適配器:

AdvisorAdapterRegistrationManagerBeanPostProcessor的一個實現類,其主要的作用爲容器中管理的Bean註冊一個面向切面編程的通知適配器,以便在Spring容器爲所管理的Bean進行面向切面編程時提供方便,其源碼如下:

  1. //爲容器中管理的Bean註冊一個面向切面編程的通知適配器  
  2. public 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實例對象是一個切面通知適配器,則向容器的註冊this.advisorAdapterRegistry.registerAdvisorAdapter((AdvisorAdapter) bean);  
  17.         }  
  18.         return bean;  
  19.     }  
  20. }  

其他的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方法(配置了lazy-init預實例化屬性的除外)向IoC容器索取Bean時,容器創建Bean實例對象,並且對Bean實例對象進行屬性依賴注入,AbstractAutoWireCapableBeanFactory的populateBean方法就是實現Bean屬性依賴注入的功能,其主要源碼如下:

  1. protected 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).DefaultSingletonBeanRegistryregisterDependentBean方法對屬性注入:

  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容器自動執行的,容器是不會智能判斷的,如果配置不當,將會帶來無法預料的後果,所以自動依賴注入特性在使用時還是綜合考慮。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章