1. 程式人生 > >Spring開閉原則的表現-BeanPostProcessor擴充套件點-1

Spring開閉原則的表現-BeanPostProcessor擴充套件點-1

http://jinnianshilongnian.iteye.com/blog/1489787

上接繼續分析,在分析上篇的問題之前,我們需要了解下BeanPostProcessor概念和Spring容器建立Bean的流程。

一、BeanPostProcessor是什麼

介面定義

Java程式碼  收藏程式碼
  1. package org.springframework.beans.factory.config;  
  2. public interface BeanPostProcessor {  
  3.     Object postProcessBeforeInitialization(Object bean, String beanName) throws
     BeansException;  
  4.     Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;  
  5. }  

BeanPostProcessor是Spring容器的一個擴充套件點,可以進行自定義的例項化、初始化、依賴裝配、依賴檢查等流程,即可以覆蓋預設的例項化,也可以增強初始化、依賴注入、依賴檢查等流程,其javadoc有如下描述:

    e.g. checking for marker interfaces or wrapping them with proxies.

    大體意思是可以檢查相應的標識介面完成一些自定義功能實現,如包裝目標物件到代理物件。

我們可以看到BeanPostProcessor一共有兩個回撥方法postProcessBeforeInitialization和postProcessAfterInitialization,那這兩個方法會在什麼Spring執行流程中的哪個步驟執行呢?還有目前Spring提供哪些相應的實現呢?

Spring還提供了BeanPostProcessor一些其他介面實現,來完成除例項化外的其他功能,後續詳細介紹。

二、通過原始碼看看建立一個Bean例項的具體執行流程:


 

AbstractApplicationContext內部使用DefaultListableBeanFactory,且DefaultListableBeanFactory繼承AbstractAutowireCapableBeanFactory,因此我們此處分析AbstractAutowireCapableBeanFactory即可。

一、AbstractAutowireCapableBeanFactory的createBean方法程式碼如下:

Java程式碼  收藏程式碼
  1. protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {  
  2.     resolveBeanClass(mbd, beanName); /1解析Bean的class  
  3.     mbd.prepareMethodOverrides(); //2 方法注入準備  
  4.     Object bean = resolveBeforeInstantiation(beanName, mbd); //3 第一個BeanPostProcessor擴充套件點  
  5.     if (bean != null) { //4 如果3處的擴充套件點返回的bean不為空,直接返回該bean,後續流程不需要執行  
  6.         return bean;  
  7.     }   
  8.     Object beanInstance = doCreateBean(beanName, mbd, args); //5 執行spring的建立bean例項的流程啦  
  9.     return beanInstance;  
  10. }  

 0.3 第一個BeanPostProcessor擴充套件點(只有InstantiationAwareBeanPostProcessor介面的實現才會被呼叫)

二、AbstractAutowireCapableBeanFactory的resolveBeforeInstantiation方法程式碼如下:

Java程式碼  收藏程式碼
  1. protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {  
  2.         Object bean = null;  
  3.         if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {  
  4.             // Make sure bean class is actually resolved at this point.  
  5.             if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {  
  6.                 //3.1、執行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation回撥方法  
  7.                 bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);  
  8.                 if (bean != null) {  
  9.                     //3.2、執行InstantiationAwareBeanPostProcessor的postProcessAfterInitialization回撥方法  
  10.                     bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);  
  11.                 }  
  12.             }  
  13.             mbd.beforeInstantiationResolved = (bean != null);  
  14.         }  
  15.         return bean;  
  16. }   

通過如上程式碼可以進行例項化的預處理(自定義例項化bean,如建立相應的代理物件)和後處理(如進行自定義例項化的bean的依賴裝配)。

三、AbstractAutowireCapableBeanFactory的doCreateBean方法程式碼如下:

Java程式碼  收藏程式碼
  1. // 6、通過BeanWrapper例項化Bean   
  2. BeanWrapper instanceWrapper = null;  
  3. if (mbd.isSingleton()) {  
  4.     instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);  
  5. }  
  6. if (instanceWrapper == null) {  
  7.     instanceWrapper = createBeanInstance(beanName, mbd, args);  
  8. }  
  9. final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);  
  10. Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);  
  11. //7、執行MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition流程  
  12. synchronized (mbd.postProcessingLock) {  
  13.     if (!mbd.postProcessed) {  
  14.         applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);  
  15.         mbd.postProcessed = true;  
  16.     }  
  17. }  
  18. // 8、及早暴露單例Bean引用,從而允許setter注入方式的迴圈引用  
  19. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&  
  20.         isSingletonCurrentlyInCreation(beanName));  
  21. if (earlySingletonExposure) {  
  22.     //省略log  
  23.     addSingletonFactory(beanName, new ObjectFactory() {  
  24.         public Object getObject() throws BeansException {  
  25.             //8.1、呼叫SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference返回一個需要暴露的Bean(例如包裝目標物件到代理物件)  
  26.             return getEarlyBeanReference(beanName, mbd, bean);  
  27.         }  
  28.     });  
  29. }  
  30. Object exposedObject = bean;  
  31. try {  
  32.     populateBean(beanName, mbd, instanceWrapper); //9、組裝-Bean依賴  
  33.     if (exposedObject != null) {  
  34.         exposedObject = initializeBean(beanName, exposedObject, mbd); //10、初始化Bean  
  35.     }  
  36. }  
  37. catch (Throwable ex) {  
  38.     //省略異常  
  39. }  
  40. //11如果是及早暴露單例bean,通過getSingleton觸發3.1處的getEarlyBeanReference呼叫獲取要及早暴露的單例Bean  
  41.     if (earlySingletonExposure) {  
  42.     Object earlySingletonReference = getSingleton(beanName, false);  
  43.     if (earlySingletonReference != null) {  
  44.         if (exposedObject == bean) {  
  45.             exposedObject = earlySingletonReference;  
  46.         }  
  47.         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {  
  48.             String[] dependentBeans = getDependentBeans(beanName);  
  49.             Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);  
  50.             for (String dependentBean : dependentBeans) {  
  51.                 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {  
  52.                     actualDependentBeans.add(dependentBean);  
  53.                 }  
  54.             }  
  55.             if (!actualDependentBeans.isEmpty()) {  
  56.                 throw new BeanCurrentlyInCreationException(beanName,  
  57.                         "Bean with name '" + beanName + "' has been injected into other beans [" +  
  58.                         StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +  
  59.                         "] in its raw version as part of a circular reference, but has eventually been " +  
  60.                         "wrapped. This means that said other beans do not use the final version of the " +  
  61.                         "bean. This is often the result of over-eager type matching - consider using " +  
  62.                         "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");  
  63.             }  
  64.         }  
  65.     }  
  66. }  
  67. //12、註冊Bean的銷燬回撥  
  68. try {  
  69.     registerDisposableBeanIfNecessary(beanName, bean, mbd);  
  70. }  
  71. catch (BeanDefinitionValidationException ex) {  
  72.     throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);  
  73. }  

四、AbstractAutowireCapableBeanFactory的populateBean方法程式碼如下:

Java程式碼  收藏程式碼
  1. //9、組裝-Bean  
  2. protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {  
  3.     PropertyValues pvs = mbd.getPropertyValues();  
  4.     //省略部分程式碼  
  5.     //9.1、通過InstantiationAwareBeanPostProcessor擴充套件點允許自定義裝配流程(如@Autowired支援等)  
  6.     //執行InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation  
  7.     boolean continueWithPropertyPopulation = true;  
  8.     if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {  
  9.         for (BeanPostProcessor bp : getBeanPostProcessors()) {  
  10.             if (bp instanceof InstantiationAwareBeanPostProcessor) {  
  11.                 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;  
  12.                 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {  
  13.                     continueWithPropertyPopulation = false;  
  14.                     break;  
  15.                 }  
  16.             }  
  17.         }  
  18.     }  
  19.     if (!continueWithPropertyPopulation) {  
  20.         return;  
  21.     }  
  22.     if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||  
  23.             mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
  24.         MutablePropertyValues newPvs = new MutablePropertyValues(pvs);  
  25.         // 9. 2、自動裝配(根據name/type)  
  26.         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {  
  27.             autowireByName(beanName, mbd, bw, newPvs);  
  28.         }  
  29.         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
  30.             autowireByType(beanName, mbd, bw, newPvs);  
  31.         }  
  32.         pvs = newPvs;  
  33.     }  
  34.     boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();  
  35.     boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);  
  36.     //9. 3、執行InstantiationAwareBeanPostProcessor的postProcessPropertyValues  
  37.     if (hasInstAwareBpps || needsDepCheck) {  
  38.         PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);  
  39.         if (hasInstAwareBpps) {  
  40.             for (BeanPostProcessor bp : getBeanPostProcessors()) {  
  41.                 if (bp instanceof InstantiationAwareBeanPostProcessor) {  
  42.                     InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;  
  43.                     pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);  
  44.                     if (pvs == null) {  
  45.                         return;  
  46.                     }  
  47.                 }  
  48.             }  
  49.         }  
  50.         //9. 4、執行依賴檢查  
  51.         if (needsDepCheck) {  
  52.             checkDependencies(beanName, mbd, filteredPds, pvs);  
  53.         }  
  54.     }  
  55.     //9. 5、應用依賴注入  
  56.     applyPropertyValues(beanName, mbd, bw, pvs);  
  57. }  

五、AbstractAutowireCapableBeanFactory的initializeBean方法程式碼如下:

Java程式碼  收藏程式碼
  1.      //10、例項化Bean  
  2.      protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {  
  3. //10.1、呼叫Aware介面注入(BeanNameAware、BeanClassLoaderAware、BeanFactoryAware)  
  4. invokeAwareMethods(beanName, bean);//此處省略部分程式碼  
  5. //10.2、執行BeanPostProcessor擴充套件點的postProcessBeforeInitialization進行修改例項化Bean  
  6. Object wrappedBean = bean;  
  7. if (mbd == null || !mbd.isSynthetic()) {  
  8.     wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);  
  9. }  
  10. //10.3、執行初始化回撥(1、呼叫InitializingBean的afterPropertiesSet  2、呼叫自定義的init-method)  
  11. try {  
  12.     invokeInitMethods(beanName, wrappedBean, mbd);  
  13. }  
  14. catch (Throwable ex) {  
  15.     //異常省略  
  16. }  
  17. //10.4、執行BeanPostProcessor擴充套件點的postProcessAfterInitialization進行修改例項化Bean  
  18. if (mbd == null || !mbd.isSynthetic()) {  
  19.     wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);  
  20. }  
  21. return wrappedBean;  

三、建立一個Bean例項的執行流程簡化:

protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args); 建立Bean

(1、resolveBeanClass(mbd, beanName); 解析Bean class,若class配置錯誤將丟擲CannotLoadBeanClassException;

(2、mbd.prepareMethodOverrides(); 準備和驗證配置的方法注入,若驗證失敗丟擲BeanDefinitionValidationException

(3、Object bean = resolveBeforeInstantiation(beanName, mbd); 第一個BeanPostProcessor擴充套件點,此處只執行InstantiationAwareBeanPostProcessor型別的BeanPostProcessor Bean;

(3.1、bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);執行InstantiationAwareBeanPostProcessor的例項化的預處理回撥方法postProcessBeforeInstantiation(自定義的例項化,如建立代理);

(3.2、bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);執行InstantiationAwareBeanPostProcessor的例項化的後處理回撥方法postProcessAfterInitialization(如依賴注入),如果3.1處返回的Bean不為null才執行;

(4、如果3處的擴充套件點返回的bean不為空,直接返回該bean,後續流程不需要執行;

(5、Object beanInstance = doCreateBean(beanName, mbd, args); 執行spring的建立bean例項的流程;

(6、createBeanInstance(beanName, mbd, args); 例項化Bean

(6.2.1如果之前已經解析過構造器

(6.2.1.1 autowireConstructor:有參呼叫autowireConstructor例項化

(6.2.1.2、instantiateBean:無參呼叫instantiateBean例項化;

(6.2.2如果之前沒有解析過構造器:

(6.2.2.1、通過SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors回撥方法解析構造器,第二個BeanPostProcessor擴充套件點,返回第一個解析成功(返回值不為null)的構造器組,如AutowiredAnnotationBeanPostProcessor實現將自動掃描通過@Autowired/@Value註解的構造器從而可以完成構造器注入,請參考【第十二章】零配置 之 12.2 註解實現Bean依賴注入 ——跟我學spring3 ;

(6.2.2.2、autowireConstructor:如果(6.2.2.1返回的不為null,且是有參構造器,呼叫autowireConstructor例項化;

(6.2.2.3、instantiateBean:否則呼叫無參構造器例項化;

(7、applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);第三個BeanPostProcessor擴充套件點,執行Bean定義的合併;

(7.1、執行MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition回撥方法,進行bean定義的合併;

(8、addSingletonFactory(beanName, new ObjectFactory() {

                            public Object getObject() throws BeansException {

                                   return getEarlyBeanReference(beanName, mbd, bean);

                            }

                     }); 及早暴露單例Bean引用,從而允許setter注入方式的迴圈引用

(8.1、SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference;第四個BeanPostProcessor擴充套件點,當存在迴圈依賴時,通過該回調方法獲取及早暴露的Bean例項;

(9、populateBean(beanName, mbd, instanceWrapper);裝配Bean依賴

(9.1、InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation;第五個BeanPostProcessor擴充套件點,在例項化Bean之後,所有其他裝配邏輯之前執行,如果false將阻止其他的InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation的執行和從(9.2到(9.5的執行,通常返回true;

(9.2、autowireByName、autowireByType:根據名字和型別進行自動裝配,自動裝配的知識請參考3.3.3  自動裝配;

(9.3、InstantiationAwareBeanPostProcessor的postProcessPropertyValues:第六個BeanPostProcessor擴充套件點,完成其他定製的一些依賴注入,如AutowiredAnnotationBeanPostProcessor執行@Autowired註解注入,CommonAnnotationBeanPostProcessor執行@Resource等註解的注入,PersistenceAnnotationBeanPostProcessor執行@ PersistenceContext等JPA註解的注入,RequiredAnnotationBeanPostProcessor執行@ Required註解的檢查等等,請參考【第十二章】零配置 之 12.2 註解實現Bean依賴注入 ——跟我學spring3

(9.5、applyPropertyValues:應用明確的setter屬性注入,請參考【第三章】 DI 之 3.1 DI的配置使用 ——跟我學spring3 

(10、exposedObject = initializeBean(beanName, exposedObject, mbd); 執行初始化Bean流程;

(10.1、invokeAwareMethods(BeanNameAware、BeanClassLoaderAware、BeanFactoryAware:呼叫一些Aware標識介面注入如BeanName、BeanFactory;

(10.2、BeanPostProcessor的postProcessBeforeInitialization:第七個擴充套件點,在呼叫初始化之前完成一些定製的初始化任務,如BeanValidationPostProcessor完成JSR-303 @Valid註解Bean驗證,InitDestroyAnnotationBeanPostProcessor完成@PostConstruct註解的初始化方法呼叫,ApplicationContextAwareProcessor完成一些Aware介面的注入(如EnvironmentAware、ResourceLoaderAware、ApplicationContextAware),其返回值將替代原始的Bean物件;

(10.3、invokeInitMethods : 呼叫初始化方法;

(10.3.1、InitializingBean的afterPropertiesSet :呼叫InitializingBean的afterPropertiesSet回撥方法;

(10.3.2、通過xml指定的自定義init-metho:呼叫通過xml配置的自定義init-method

(10.3.3、BeanPostProcessor的postProcessAfterInitialization :第八個擴充套件點,AspectJAwareAdvisorAutoProxyCreator(完成xml風格的AOP配置(<aop:config>)的目標物件包裝到AOP代理物件)、AnnotationAwareAspectJAutoProxyCreator(完成@Aspectj註解風格(<aop:aspectj-autoproxy> @Aspect)的AOP配置的目標物件包裝到AOP代理物件),其返回值將替代原始的Bean物件;

(11、if (earlySingletonExposure) {

                     Object earlySingletonReference = getSingleton(beanName, false);

……

      } :如果是earlySingleExposure,呼叫getSingle方法獲取Bean例項;

earlySingleExposure =(mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName))

只要單例Bean且允許迴圈引用(預設true)且當前單例Bean正在建立中

(11.1、如果是earlySingletonExposure呼叫getSingleton將觸發【8】處ObjectFactory.getObject()的呼叫,通過【8.1】處的getEarlyBeanReference獲取相關Bean(如包裝目標物件的代理Bean);(在迴圈引用Bean時可能引起Spring事務處理時自我呼叫的解決方案及一些實現方式的風險);

(12、registerDisposableBeanIfNecessary(beanName, bean, mbd) : 註冊Bean的銷燬方法(只有非原型Bean可註冊);

(12.1、單例Bean的銷燬流程

(12.1.1、DestructionAwareBeanPostProcessor的postProcessBeforeDestruction : 第九個擴充套件點,如InitDestroyAnnotationBeanPostProcessor完成@PreDestroy註解的銷燬方法註冊和呼叫;

(12.1.2、DisposableBean的destroy:註冊/呼叫DisposableBean的destroy銷燬方法;

(12.1.3、通過xml指定的自定義destroy-method :註冊/呼叫通過XML指定的destroy-method銷燬方法;

(12.1.2、Scope的registerDestructionCallback:註冊自定義的Scope的銷燬回撥方法,如RequestScope、SessionScope等;其流程和【12.1 單例Bean的銷燬流程一樣】,關於自定義Scope請參考【第三章】 DI 之 3.4 Bean的作用域 ——跟我學spring3

(13、到此Bean例項化、依賴注入、初始化完畢可以返回建立好的bean了。

從上面的流程我們可以看到BeanPostProcessor一個使用了九個擴充套件點,其實還一個擴充套件點(SmartInstantiationAwareBeanPostProcessor的predictBeanType在下一篇介紹),接下來我們看看BeanPostProcessor這些擴充套件點都主要完成什麼功能及常見的BeanPostProcessor。

我將在下一帖子中使用例子來解析這八個擴充套件點的主要功能,及一些Spring預設提供的BeanPostProcessor主要作用。


上接繼續分析,在分析上篇的問題之前,我們需要了解下BeanPostProcessor概念和Spring容器建立Bean的流程。