02.25 Spring的Bean的生命週期(源碼分析)

一、 BeanPostProcessor

接口定義

<code>package org.springframework.beans.factory.config;  public interface BeanPostProcessor {      Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;      Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;  }  /<code>

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

<code>e.g. checking for marker interfaces or wrapping them with proxies.​大體意思是可以檢查相應的標識接口完成一些自定義功能實現,如包裝目標對象到代理對象。/<code>

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

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

二、 通過源代碼看看創建一個Bean實例的具體執行流程

Spring的Bean的生命週期(源碼分析)

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

2.1 createBean

AbstractAutowireCapableBeanFactory的createBean方法代碼如下:

<code>protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {      resolveBeanClass(mbd, beanName); /1解析Bean的class      mbd.prepareMethodOverrides(); //2 方法注入準備      Object bean = resolveBeforeInstantiation(beanName, mbd); //3 第一個BeanPostProcessor擴展點      if (bean != null) { //4 如果3處的擴展點返回的bean不為空,直接返回該bean,後續流程不需要執行          return bean;      }       Object beanInstance = doCreateBean(beanName, mbd, args); //5 執行spring的創建bean實例的流程啦      return beanInstance;  }  /<code>

2.2 resolveBeforeInstantiation

AbstractAutowireCapableBeanFactory的resolveBeforeInstantiation方法代碼如下:

<code>protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {          Object bean = null;          if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {              // Make sure bean class is actually resolved at this point.              if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {                  //3.1、執行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation回調方法                  bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);                  if (bean != null) {                      //3.2、執行InstantiationAwareBeanPostProcessor的postProcessAfterInitialization回調方法                      bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);                  }              }              mbd.beforeInstantiationResolved = (bean != null);          }          return bean;  } /<code>

2.3 doCreateBean

AbstractAutowireCapableBeanFactory的doCreateBean方法代碼如下:

<code>        // 6、通過BeanWrapper實例化Bean           BeanWrapper instanceWrapper = null;          if (mbd.isSingleton()) {              instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);          }          if (instanceWrapper == null) {              instanceWrapper = createBeanInstance(beanName, mbd, args);          }          final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);          Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);            //7、執行MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition流程          synchronized (mbd.postProcessingLock) {              if (!mbd.postProcessed) {                  applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);                  mbd.postProcessed = true;              }          }          // 8、及早暴露單例Bean引用,從而允許setter注入方式的循環引用          boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&                  isSingletonCurrentlyInCreation(beanName));          if (earlySingletonExposure) {              //省略log              addSingletonFactory(beanName, new ObjectFactory() {                  public Object getObject() throws BeansException {                      //8.1、調用SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference返回一個需要暴露的Bean(例如包裝目標對象到代理對象)                      return getEarlyBeanReference(beanName, mbd, bean);                  }              });          }                    Object exposedObject = bean;          try {              populateBean(beanName, mbd, instanceWrapper); //9、組裝-Bean依賴              if (exposedObject != null) {                  exposedObject = initializeBean(beanName, exposedObject, mbd); //10、初始化Bean              }          }          catch (Throwable ex) {              //省略異常          }              //11如果是及早暴露單例bean,通過getSingleton觸發3.1處的getEarlyBeanReference調用獲取要及早暴露的單例Bean          if (earlySingletonExposure) {              Object earlySingletonReference = getSingleton(beanName, false);              if (earlySingletonReference != null) {                  if (exposedObject == bean) {                      exposedObject = earlySingletonReference;                  }                  else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {                      String[] dependentBeans = getDependentBeans(beanName);                      Set<string> actualDependentBeans = new LinkedHashSet<string>(dependentBeans.length);                      for (String dependentBean : dependentBeans) {                          if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {                              actualDependentBeans.add(dependentBean);                          }                      }                      if (!actualDependentBeans.isEmpty()) {                          throw new BeanCurrentlyInCreationException(beanName,                                  "Bean with name '" + beanName + "' has been injected into other beans [" +                                  StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +                                  "] in its raw version as part of a circular reference, but has eventually been " +                                  "wrapped. This means that said other beans do not use the final version of the " +                                  "bean. This is often the result of over-eager type matching - consider using " +                                  "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");                      }                  }              }          }          //12、註冊Bean的銷燬回調          try {              registerDisposableBeanIfNecessary(beanName, bean, mbd);          }          catch (BeanDefinitionValidationException ex) {              throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);          }            return exposedObject;  }  /<string>/<string>/<code>

2.4 populateBean

AbstractAutowireCapableBeanFactory的populateBean方法代碼如下:

<code>//9、組裝-Bean  protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {      PropertyValues pvs = mbd.getPropertyValues();      //省略部分代碼      //9.1、通過InstantiationAwareBeanPostProcessor擴展點允許自定義裝配流程(如@Autowired支持等)      //執行InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation      boolean continueWithPropertyPopulation = true;      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {          for (BeanPostProcessor bp : getBeanPostProcessors()) {              if (bp instanceof InstantiationAwareBeanPostProcessor) {                  InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;                  if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {                      continueWithPropertyPopulation = false;                      break;                  }              }          }      }      if (!continueWithPropertyPopulation) {          return;      }      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||              mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {          MutablePropertyValues newPvs = new MutablePropertyValues(pvs);          // 9. 2、自動裝配(根據name/type)          if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {              autowireByName(beanName, mbd, bw, newPvs);          }          if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {              autowireByType(beanName, mbd, bw, newPvs);          }          pvs = newPvs;      }      boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();      boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);          //9. 3、執行InstantiationAwareBeanPostProcessor的postProcessPropertyValues      if (hasInstAwareBpps || needsDepCheck) {          PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);          if (hasInstAwareBpps) {              for (BeanPostProcessor bp : getBeanPostProcessors()) {                  if (bp instanceof InstantiationAwareBeanPostProcessor) {                      InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;                      pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);                      if (pvs == null) {                          return;                      }                  }              }          }          //9. 4、執行依賴檢查          if (needsDepCheck) {              checkDependencies(beanName, mbd, filteredPds, pvs);          }      }      //9. 5、應用依賴注入      applyPropertyValues(beanName, mbd, bw, pvs);  }  /<code> 

2.5 initializeBean

AbstractAutowireCapableBeanFactory的initializeBean方法代碼如下:

<code>     //10、實例化Bean       protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {  //10.1、調用Aware接口注入(BeanNameAware、BeanClassLoaderAware、BeanFactoryAware)  invokeAwareMethods(beanName, bean);//此處省略部分代碼  //10.2、執行BeanPostProcessor擴展點的postProcessBeforeInitialization進行修改實例化Bean  Object wrappedBean = bean;  if (mbd == null || !mbd.isSynthetic()) {      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);  }  //10.3、執行初始化回調(1、調用InitializingBean的afterPropertiesSet  2、調用自定義的init-method)  try {      invokeInitMethods(beanName, wrappedBean, mbd);  }  catch (Throwable ex) {      //異常省略  }  //10.4、執行BeanPostProcessor擴展點的postProcessAfterInitialization進行修改實例化Bean  if (mbd == null || !mbd.isSynthetic()) {      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);  }  return wrappedBean;  /<code>

三、創建一個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

有關方法注入知識請參考【第三章】 DI 之 3.3 更多DI的知識 ——跟我學spring3 3.3.5 方法注入;


(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.1、instantiateUsingFactoryMethod 工廠方法實例化;請參考【http://jinnianshilongnian.iteye.com/blog/1413857】

(6.2、構造器實例化,請參考【http://jinnianshilongnian.iteye.com/blog/1413857】;

(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() {**

<code>                        **public Object getObject() throws BeansException {**​                               **return getEarlyBeanReference(beanName, mbd, bean);**​                        **}**​                 **});**  及早暴露單例Bean引用,從而允許setter注入方式的循環引用/<code>

(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:根據名字和類型進行自動裝配,自動裝配的知識請參考【第三章】 DI 之 3.3 更多DI的知識 ——跟我學spring3 3.3.3 自動裝配;

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

(9.4、checkDependencies:依賴檢查,請參考【第三章】 DI 之 3.3 更多DI的知識 ——跟我學spring3 3.3.4 依賴檢查;

(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-method :調用通過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) {

<code>                 Object earlySingletonReference = getSingleton(beanName, false);        ……  } :如果是earlySingleExposure,調用getSingle方法獲取Bean實例;/<code>

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。

四、BeanPostProcessor接口及回調方法圖

Spring的Bean的生命週期(源碼分析)

從圖中我們可以看出一共五個接口,共十個回調方法,即十個擴展點,但我們之前的文章只分析了其中八個,另外兩個稍候也會解析一下是幹什麼的。

五、五個接口十個擴展點解析

1**、InstantiationAwareBeanPostProcessor**:實例化Bean後置處理器(繼承BeanPostProcessor)

postProcessBeforeInstantiation :在實例化目標對象之前執行,可以自定義實例化邏輯,如返回一個代理對象等,(3.1處執行;如果此處返回的Bean不為null將中斷後續Spring創建Bean的流程,且只執行postProcessAfterInitialization回調方法,如當AbstractAutoProxyCreator的實現者註冊了TargetSourceCreator(創建自定義的TargetSource)將改變執行流程,不註冊TargetSourceCreator我們默認使用的是SingletonTargetSource(即AOP代理直接保證目標對象),此處我們還可以使用如ThreadLocalTargetSource(線程綁定的Bean)、CommonsPoolTargetSource(實例池的Bean)等等,大家可以去spring官方文檔瞭解TargetSource詳情;

postProcessAfterInitialization : Bean實例化完畢後執行的後處理操作,所有初始化邏輯、裝配邏輯之前執行,如果返回false將阻止其他的InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation的執行,(3.2和(9.1處執行;在此處可以執行一些初始化邏輯或依賴裝配邏輯;

postProcessPropertyValues :完成其他定製的一些依賴注入和依賴檢查等,如AutowiredAnnotationBeanPostProcessor執行@Autowired註解注入,CommonAnnotationBeanPostProcessor執行@Resource等註解的注入,PersistenceAnnotationBeanPostProcessor執行@ PersistenceContext等JPA註解的注入,RequiredAnnotationBeanPostProcessor執行@ Required註解的檢查等等,(9.3處執行;


2**、MergedBeanDefinitionPostProcessor**:合併Bean定義後置處理器 (繼承BeanPostProcessor)

postProcessMergedBeanDefinition:執行Bean定義的合併,在(7.1處執行,且在實例化完Bean之後執行;


3**、SmartInstantiationAwareBeanPostProcessor**:智能實例化Bean後置處理器(繼承InstantiationAwareBeanPostProcessor)

predictBeanType:預測Bean的類型,返回第一個預測成功的Class類型,如果不能預測返回null;當你調用BeanFactory.getType(name)時當通過Bean定義無法得到Bean類型信息時就調用該回調方法來決定類型信息;BeanFactory.isTypeMatch(name, targetType)用於檢測給定名字的Bean是否匹配目標類型(如在依賴注入時需要使用);

determineCandidateConstructors:檢測Bean的構造器,可以檢測出多個候選構造器,再有相應的策略決定使用哪一個,如AutowiredAnnotationBeanPostProcessor實現將自動掃描通過@Autowired/@Value註解的構造器從而可以完成構造器注入,請參考【第十二章】零配置 之 12.2 註解實現Bean依賴注入 ——跟我學spring3 ,(6.2.2.1處執行;

getEarlyBeanReference:當正在創建A時,A依賴B,此時通過(8將A作為ObjectFactory放入單例工廠中進行early expose,此處B需要引用A,但A正在創建,從單例工廠拿到ObjectFactory(其通過getEarlyBeanReference獲取及早暴露Bean),從而允許循環依賴,此時AspectJAwareAdvisorAutoProxyCreator(完成xml風格的AOP配置(aop:config)將目標對象(A)包裝到AOP代理對象)或AnnotationAwareAspectJAutoProxyCreator(完成@Aspectj註解風格(aop:aspectj-autoproxy @Aspect)將目標對象(A)包裝到AOP代理對象),其返回值將替代原始的Bean對象,即此時通過early reference能得到正確的代理對象,(8.1處實施;如果此處執行了,(10.3.3處的AspectJAwareAdvisorAutoProxyCreator或AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization將不執行,即這兩個回調方法是二選一的;


4**、BeanPostProcessor**:Bean後置處理器

postProcessBeforeInitialization:實例化、依賴注入完畢,在調用顯示的初始化之前完成一些定製的初始化任務,如BeanValidationPostProcessor完成JSR-303 @Valid註解Bean驗證,InitDestroyAnnotationBeanPostProcessor完成@PostConstruct註解的初始化方法調用,ApplicationContextAwareProcessor完成一些Aware接口的注入(如EnvironmentAware、ResourceLoaderAware、ApplicationContextAware),其返回值將替代原始的Bean對象;(10.2處執行;

postProcessAfterInitialization:實例化、依賴注入、初始化完畢時執行,如AspectJAwareAdvisorAutoProxyCreator(完成xml風格的AOP配置(aop:config)的目標對象包裝到AOP代理對象)、AnnotationAwareAspectJAutoProxyCreator(完成@Aspectj註解風格(aop:aspectj-autoproxy @Aspect)的AOP配置的目標對象包裝到AOP代理對象),其返回值將替代原始的Bean對象;(10.3.3處執行;此處需要參考getEarlyBeanReference;


5**、DestructionAwareBeanPostProcessor**:銷燬Bean後置處理器(繼承BeanPostProcessor)

postProcessBeforeDestruction:銷燬後處理回調方法,該回調只能應用到單例Bean,如InitDestroyAnnotationBeanPostProcessor完成@PreDestroy註解的銷燬方法調用;(12.1.1處執行。

六、內置的一些BeanPostProcessor

Spring的Bean的生命週期(源碼分析)

此圖只有內置的一部分。


1、ApplicationContextAwareProcessor

容器啟動時會自動註冊。注入那些實現ApplicationContextAware、MessageSourceAware、ResourceLoaderAware、EnvironmentAware、

EmbeddedValueResolverAware、ApplicationEventPublisherAware標識接口的Bean需要的相應實例,在postProcessBeforeInitialization回調方法中進行實施,即(10.2處實施。


2、CommonAnnotationBeanPostProcessor

CommonAnnotationBeanPostProcessor繼承InitDestroyAnnotationBeanPostProcessor,當在配置文件有context:annotation-config或context:component-scan會自動註冊。


提供對JSR-250規範註解的支持@javax.annotation.Resource、@javax.annotation.PostConstruct和@javax.annotation.PreDestroy等的支持。


2.1、通過@Resource註解進行依賴注入:

<code>postProcessPropertyValues:通過此回調進行@Resource註解的依賴注入;(9.3處實施;/<code>

2.2、用於執行@PostConstruct 和@PreDestroy 註解的初始化和銷燬方法的擴展點:

<code>postProcessBeforeInitialization()將會調用bean的@PostConstruct方法;(10.2處實施;​postProcessBeforeDestruction()將會調用單例 Bean的@PreDestroy方法(此回調方法會在容器銷燬時調用),(12.1.1處實施。/<code> 


詳見【第十二章】零配置 之 12.2 註解實現Bean依賴注入 ——跟我學spring3,JSR-250註解部分。


3、AutowiredAnnotationBeanPostProcessor

當在配置文件有context:annotation-config或context:component-scan會自動註冊。


提供對JSR-330規範註解的支持和Spring自帶註解的支持。


3.1、Spring自帶註解的依賴注入支持,@Autowired和@Value:

<code>determineCandidateConstructors :決定候選構造器;詳見【12.2中的構造器注入】;(6.2.2.1處實施;/<code>

postProcessPropertyValues :進行依賴注入;詳見【12.2中的字段注入和方法參數注入】;(9.3處實施;

3.2、對JSR-330規範註解的依賴注入支持,@Inject:

<code>同2.1類似只是查找使用的註解不一樣;/<code>


詳見【第十二章】零配置 之 12.2 註解實現Bean依賴注入 ——跟我學spring3,Spring自帶依賴注入註解和 JSR-330註解部分。


4、RequiredAnnotationBeanPostProcessor

當在配置文件有context:annotation-config或context:component-scan會自動註冊。


4.1、提供對@ Required註解的方法進行依賴檢查支持:

<code>postProcessPropertyValues:如果檢測到沒有進行依賴注入時拋出BeanInitializationException異常;(9.3處實施;/<code>


詳見【第十二章】零配置 之 12.2 註解實現Bean依賴注入 ——跟我學spring3,@Required**:依賴檢查**。


5、PersistenceAnnotationBeanPostProcessor

當在配置文件有context:annotation-config或context:component-scan會自動註冊。


5.1、通過對JPA @ javax.persistence.PersistenceUnit和@ javax.persistence.PersistenceContext註解進行依賴注入的支持;

<code>postProcessPropertyValues : 根據@PersistenceUnit/@PersistenceContext進行EntityManagerFactory和EntityManager的支持;/<code>


6、AbstractAutoProxyCreator

AspectJAwareAdvisorAutoProxyCreator和AnnotationAwareAspectJAutoProxyCreator都是繼承AbstractAutoProxyCreator,AspectJAwareAdvisorAutoProxyCreator提供對(aop:config)聲明式AOP的支持,AnnotationAwareAspectJAutoProxyCreator提供對(aop:aspectj-autoproxy)註解式(@AspectJ)AOP的支持,因此只需要分析AbstractAutoProxyCreator即可。


當使用aop:config配置時自動註冊AspectJAwareAdvisorAutoProxyCreator,而使用aop:aspectj-autoproxy時會自動註冊AnnotationAwareAspectJAutoProxyCreator。

6.1、predictBeanType:預測Bean的類型,如果目標對象被AOP代理對象包裝,此處將返回AOP代理對象的類型;

<code>public Class> predictBeanType(Class> beanClass, String beanName) {          Object cacheKey = getCacheKey(beanClass, beanName);          return this.proxyTypes.get(cacheKey); //獲取代理對象類型,可能返回null  }  /<code>

6.2、postProcessBeforeInstantiation:

<code>public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException {      //1、得到一個緩存的唯一key(根據beanClass和beanName生成唯一key)      Object cacheKey = getCacheKey(beanClass, beanName);      //2、如果當前targetSourcedBeans(通過自定義TargetSourceCreator創建的TargetSource)不包含cacheKey      if (!this.targetSourcedBeans.contains(cacheKey)) {          //2.1、advisedBeans(已經被增強的Bean,即AOP代理對象)中包含當前cacheKey或nonAdvisedBeans(不應該被增強的Bean)中包含當前cacheKey 返回null,即走Spring默認流程          if (this.advisedBeans.contains(cacheKey) || this.nonAdvisedBeans.contains(cacheKey)) {              return null;          }          //2.2、如果是基礎設施類(如Advisor、Advice、AopInfrastructureBean的實現)不進行處理          //2.2、shouldSkip 默認false,可以生成子類覆蓋,如AspectJAwareAdvisorAutoProxyCreator覆蓋    (if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) return true;  即如果是自己就跳過)          if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {              this.nonAdvisedBeans.add(cacheKey);//在不能增強的Bean列表緩存當前cacheKey              return null;          }      }        //3、開始創建AOP代理對象      //3.1、配置自定義的TargetSourceCreator進行TargetSource創建      TargetSource targetSource = getCustomTargetSource(beanClass, beanName);      if (targetSource != null) {          //3.2、如果targetSource不為null 添加到targetSourcedBeans緩存,並創建AOP代理對象          this.targetSourcedBeans.add(beanName);          // specificInterceptors即增強(包括前置增強、後置增強等等)          Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);          //3.3、創建代理對象          Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);          //3.4、將代理類型放入proxyTypes從而允許後續的predictBeanType()調用獲取          this.proxyTypes.put(cacheKey, proxy.getClass());          return proxy;      }      return null;  }  /<code> 

從如上代碼可以看出,當我們配置TargetSourceCreator進行自定義TargetSource創建時,會創建代理對象並中斷默認Spring創建流程。

6.3、getEarlyBeanReference

<code>//獲取early Bean引用(只有單例Bean才能回調該方法)  public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {      Object cacheKey = getCacheKey(bean.getClass(), beanName);      //1、將cacheKey添加到earlyProxyReferences緩存,從而避免多次重複創建      this.earlyProxyReferences.add(cacheKey);      //2、包裝目標對象到AOP代理對象(如果需要)      return wrapIfNecessary(bean, beanName, cacheKey);  }  /<code>

6.4、postProcessAfterInitialization

<code>public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {      if (bean != null) {          Object cacheKey = getCacheKey(bean.getClass(), beanName);          //1、如果之前調用過getEarlyBeanReference獲取包裝目標對象到AOP代理對象(如果需要),則不再執行          if (!this.earlyProxyReferences.contains(cacheKey)) {              //2、包裝目標對象到AOP代理對象(如果需要)              return wrapIfNecessary(bean, beanName, cacheKey);          }      }      return bean;  }  /<code>
<code>protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {      if (this.targetSourcedBeans.contains(beanName)) {//通過TargetSourceCreator進行自定義TargetSource不需要包裝          return bean;      }      if (this.nonAdvisedBeans.contains(cacheKey)) {//不應該被增強對象不需要包裝          return bean;      }      if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {//基礎設施/應該skip的不需要保證          this.nonAdvisedBeans.add(cacheKey);          return bean;      }        // 如果有增強就執行包裝目標對象到代理對象      Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);      if (specificInterceptors != DO_NOT_PROXY) {          this.advisedBeans.add(cacheKey);//將cacheKey添加到已經被增強列表,防止多次增強          Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));//創建代理對象          this.proxyTypes.put(cacheKey, proxy.getClass());//緩存代理類型          return proxy;      }      this.nonAdvisedBeans.add(cacheKey);      return bean;  }  /<code>

從如上流程可以看出 getEarlyBeanReference和postProcessAfterInitialization是二者選一的,而且單例Bean目標對象只能被增強一次,而原型Bean目標對象可能被包裝多次。

7、BeanValidationPostProcessor

默認不自動註冊,Spring3.0開始支持。

提供對JSR-303驗證規範支持。

根據afterInitialization是false/true決定調用postProcessBeforeInitialization或postProcessAfterInitialization來通過JSR-303規範驗證Bean,默認false。

8、MethodValidationPostProcessor

Spring3.1開始支持,且只支持Hibernate Validator 4.2及更高版本,從Spring 3.2起可能將採取自動檢測Bean Validation 1.1兼容的提供商且自動註冊(Bean Validation 1.1 (JSR-349)正處於草案階段,它將提供方法級別的驗證,提供對方法級別的驗證),目前默認不自動註冊。

Bean Validation 1.1草案請參考http://jcp.org/en/jsr/detail?id=349 http://beanvalidation.org/。

提供對方法參數/方法返回值的進行驗證(即前置條件/後置條件的支持),通過JSR-303註解驗證,使用方式如:

public @NotNull Object myValidMethod(@NotNull String arg1, @Max(10) int arg2)

默認只對@org.springframework.validation.annotation.Validated註解的Bean進行驗證,我們可以修改validatedAnnotationType為其他註解類型來支持其他註解驗證。而且目前只支持Hibernate Validator實現,在未來版本可能支持其他實現。

有了這東西之後我們就不需要在進行如Assert.assertNotNull()這種前置條件/後置條件的判斷了。

9、ScheduledAnnotationBeanPostProcessor

當配置文件中有task:annotation-driven自動註冊或@EnableScheduling自動註冊。

提供對註解@Scheduled任務調度的支持。

postProcessAfterInitialization:通過查找Bean對象類上的@Scheduled註解來創建ScheduledMethodRunnable對象並註冊任務調度方法(僅返回值為void且方法是無形式參數的才可以)。

可參考Spring官方文檔的任務調度章節學習@Scheduled註解任務調度。

10、AsyncAnnotationBeanPostProcessor

當配置文件中有task:annotation-driven自動註冊或@EnableAsync自動註冊。

提供對@ Async和EJB3.1的@javax.ejb.Asynchronous註解的異步調用支持。

postProcessAfterInitialization:通過ProxyFactory創建目標對象的代理對象,默認使用AsyncAnnotationAdvisor(內部使用AsyncExecutionInterceptor 通過AsyncTaskExecutor(繼承TaskExecutor)通過submit提交異步任務)。

可參考Spring官方文檔的異步調用章節學習@Async註解異步調用。

11、ServletContextAwareProcessor

在使用Web容器時自動註冊。

類似於ApplicationContextAwareProcessor,當你的Bean 實現了ServletContextAware/ ServletConfigAware會自動調用回調方法注入ServletContext/ ServletConfig。

七、BeanPostProcessor如何註冊

1、如ApplicationContextAwareProcessor會在ApplicationContext容器啟動時自動註冊,而CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor會在當你使用context:annotation-config或context:component-scan配置時自動註冊。

2、只要將BeanPostProcessor註冊到容器中,Spring會在啟動時自動獲取並註冊。

八、BeanPostProcessor的執行順序

1、如果使用BeanFactory實現,非ApplicationContext實現,BeanPostProcessor執行順序就是添加順序。

2、如果使用的是AbstractApplicationContext(實現了ApplicationContext)的實現,則通過如下規則指定順序。

2.1、PriorityOrdered(繼承了Ordered),實現了該接口的BeanPostProcessor會在第一個順序註冊,標識高優先級順序,即比實現Ordered的具有更高的優先級;

2.2、Ordered,實現了該接口的BeanPostProcessor會第二個順序註冊;

int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;//最高優先級

int LOWEST_PRECEDENCE = Integer.MAX_VALUE;//最低優先級

即數字越小優先級越高,數字越大優先級越低,如0(高優先級)——1000(低優先級)

2.3、無序的,沒有實現Ordered/ PriorityOrdered的會在第三個順序註冊;

2.4、內部Bean後處理器,實現了MergedBeanDefinitionPostProcessor接口的是內部Bean PostProcessor,將在最後且無序註冊。

3、接下來我們看看內置的BeanPostProcessor執行順序

//1註冊實現了PriorityOrdered接口的BeanPostProcessor

//2註冊實現了Ordered接口的BeanPostProcessor

AbstractAutoProxyCreator 實現了Ordered,order = Ordered.LOWEST_PRECEDENCE

MethodValidationPostProcessor 實現了Ordered,LOWEST_PRECEDENCE

ScheduledAnnotationBeanPostProcessor 實現了Ordered,LOWEST_PRECEDENCE

AsyncAnnotationBeanPostProcessor 實現了Ordered,order = Ordered.LOWEST_PRECEDENCE

//3註冊無實現任何接口的BeanPostProcessor

BeanValidationPostProcessor 無序

ApplicationContextAwareProcessor 無序

ServletContextAwareProcessor 無序

//3 註冊實現了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor,且按照實現了Ordered的順序進行註冊,沒有實現Ordered的默認為Ordered.LOWEST_PRECEDENCE。

PersistenceAnnotationBeanPostProcessor 實現了PriorityOrdered,Ordered.LOWEST_PRECEDENCE - 4

AutowiredAnnotationBeanPostProcessor 實現了PriorityOrdered,order = Ordered.LOWEST_PRECEDENCE - 2

RequiredAnnotationBeanPostProcessor 實現了PriorityOrdered,order = Ordered.LOWEST_PRECEDENCE - 1

CommonAnnotationBeanPostProcessor 實現了PriorityOrdered,Ordered.LOWEST_PRECEDENCE


從上到下順序執行,如果order相同則我們應該認為同序(誰先執行不確定,其執行順序根據註冊順序決定)。

九、完成Spring事務處理時自我調用的解決方案及一些實現方式的風險分析

場景請先參考請參考Spring事務處理時自我調用的解決方案及一些實現方式的風險中的3.3、通過BeanPostProcessor 在目標對象中注入代理對象。

分析:

Spring的Bean的生命週期(源碼分析)

問題出現在5和9處:

5、使用步驟1處註冊的SingletonFactory(ObjectFactory.getObject() 使用AnnotationAwareAspectJAutoProxyCreator的getEarlyBeanReference獲取循環引用Bean),因此此處將返回A目標對象的代理對象;


9、此處調用AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization,但發現之前調用過AnnotationAwareAspectJAutoProxyCreator的getEarlyBeanReference獲取代理對象,此處不再創建代理對象,而是直接返回目標對象,因此使用InjectBeanSelfProcessor不能注入代理對象;但此時的Spring容器中的A已經是代理對象了,因此我使用了從上下文重新獲取A代理對象的方式注入(context.getBean(beanName))。


此處的getEarlyBeanReference和postProcessAfterInitialization為什麼是二者選一的請參考之前介紹的AbstractAutoProxyCreator。


g事務處理時自我調用的解決方案及一些實現方式的風險分析

場景請先參考請參考Spring事務處理時自我調用的解決方案及一些實現方式的風險中的3.3、通過BeanPostProcessor 在目標對象中注入代理對象。

分析:

[外鏈圖片轉存中...(img-EHB5CPEj-1566178194724)]

問題出現在5和9處:

5、使用步驟1處註冊的SingletonFactory(ObjectFactory.getObject() 使用AnnotationAwareAspectJAutoProxyCreator的getEarlyBeanReference獲取循環引用Bean),因此此處將返回A目標對象的代理對象;


9、此處調用AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization,但發現之前調用過AnnotationAwareAspectJAutoProxyCreator的getEarlyBeanReference獲取代理對象,此處不再創建代理對象,而是直接返回目標對象,因此使用InjectBeanSelfProcessor不能注入代理對象;但此時的Spring容器中的A已經是代理對象了,因此我使用了從上下文重新獲取A代理對象的方式注入(context.getBean(beanName))。


此處的getEarlyBeanReference和postProcessAfterInitialization為什麼是二者選一的請參考之前介紹的AbstractAutoProxyCreator。


到此問題我們分析完畢,實際項目中的循環依賴應該儘量避免,這違反了“無環依賴原則”。


分享到:


相關文章: