一、 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實例的具體執行流程
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接口及回調方法圖
從圖中我們可以看出一共五個接口,共十個回調方法,即十個擴展點,但我們之前的文章只分析了其中八個,另外兩個稍候也會解析一下是幹什麼的。
五、五個接口十個擴展點解析
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
此圖只有內置的一部分。
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 在目標對象中注入代理對象。
分析:
問題出現在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。
到此問題我們分析完畢,實際項目中的循環依賴應該儘量避免,這違反了“無環依賴原則”。
閱讀更多 Sadlay 的文章
關鍵字: 源碼 BeanPostProcessor mbd