Spring開閉原則的表現-BeanPostProcessor擴充套件點-1
http://jinnianshilongnian.iteye.com/blog/1489787
上接繼續分析,在分析上篇的問題之前,我們需要了解下BeanPostProcessor概念和Spring容器建立Bean的流程。
一、BeanPostProcessor是什麼
介面定義
Java程式碼- package org.springframework.beans.factory.config;
- public interface BeanPostProcessor {
- Object postProcessBeforeInitialization(Object bean, String beanName) throws
- Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
- }
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程式碼- 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;
- }
0.3 第一個BeanPostProcessor擴充套件點(只有InstantiationAwareBeanPostProcessor介面的實現才會被呼叫)
二、AbstractAutowireCapableBeanFactory的resolveBeforeInstantiation方法程式碼如下:
Java程式碼- 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;
- }
通過如上程式碼可以進行例項化的預處理(自定義例項化bean,如建立相應的代理物件)和後處理(如進行自定義例項化的bean的依賴裝配)。
三、AbstractAutowireCapableBeanFactory的doCreateBean方法程式碼如下:
Java程式碼- // 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);
- }
四、AbstractAutowireCapableBeanFactory的populateBean方法程式碼如下:
Java程式碼- //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);
- }
五、AbstractAutowireCapableBeanFactory的initializeBean方法程式碼如下:
Java程式碼- //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;
三、建立一個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-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) {
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的流程。