论坛首页 Java企业应用论坛

Spring开闭原则的表现-BeanPostProcessor扩展点-1

浏览 39381 次
精华帖 (8) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2012-04-18   最后修改:2012-04-20

 

上接Spring事务处理时自我调用的解决方案及一些实现方式的风险继续分析,在分析上篇的问题之前,我们需要了解下BeanPostProcessor概念和Spring容器创建Bean的流程。

 

一、BeanPostProcessor是什么

接口定义

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;
}

BeanPostProcessorSpring容器的一个扩展点,可以进行自定义的实例化、初始化、依赖装配、依赖检查等流程,即可以覆盖默认的实例化,也可以增强初始化、依赖注入、依赖检查等流程,其javadoc有如下描述:

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

    大体意思是可以检查相应的标识接口完成一些自定义功能实现,如包装目标对象到代理对象。

我们可以看到BeanPostProcessor一共有两个回调方法postProcessBeforeInitializationpostProcessAfterInitialization,那这两个方法会在什么Spring执行流程中的哪个步骤执行呢?还有目前Spring提供哪些相应的实现呢?

 

Spring还提供了BeanPostProcessor一些其他接口实现,来完成除实例化外的其他功能,后续详细介绍。

 

 

 

二、通过源代码看看创建一个Bean实例的具体执行流程:


 

AbstractApplicationContext内部使用DefaultListableBeanFactory,且DefaultListableBeanFactory继承AbstractAutowireCapableBeanFactory,因此我们此处分析AbstractAutowireCapableBeanFactory即可。

 

一、AbstractAutowireCapableBeanFactorycreateBean方法代码如下:

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接口的实现才会被调用)

 

二、AbstractAutowireCapableBeanFactoryresolveBeforeInstantiation方法代码如下:

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的依赖装配)。

 

三、AbstractAutowireCapableBeanFactorydoCreateBean方法代码如下:

 

		// 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;
}
 

 

四、AbstractAutowireCapableBeanFactorypopulateBean方法代码如下:

	//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);
	}

 

五、AbstractAutowireCapableBeanFactoryinitializeBean方法代码如下:

       //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

1resolveBeanClass(mbd, beanName); 解析Bean class,若class配置错误将抛出CannotLoadBeanClassException

 

2mbd.prepareMethodOverrides(); 准备和验证配置的方法注入,若验证失败抛出BeanDefinitionValidationException

有关方法注入知识请参考【第三章】 DI 3.3 更多DI的知识 ——跟我学spring3 3.3.5 方法注入;

 

3Object bean = resolveBeforeInstantiation(beanName, mbd); 第一个BeanPostProcessor扩展点,此处只执行InstantiationAwareBeanPostProcessor类型的BeanPostProcessor Bean

3.1bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);执行InstantiationAwareBeanPostProcessor的实例化的预处理回调方法postProcessBeforeInstantiation(自定义的实例化,如创建代理);

3.2bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);执行InstantiationAwareBeanPostProcessor的实例化的后处理回调方法postProcessAfterInitialization(如依赖注入),如果3.1处返回的Bean不为null才执行;

 

4、如果3处的扩展点返回的bean不为空,直接返回该bean,后续流程不需要执行;

 

5Object beanInstance = doCreateBean(beanName, mbd, args); 执行spring的创建bean实例的流程;

 

 

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

6.1instantiateUsingFactoryMethod 工厂方法实例化;请参考【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.2instantiateBean无参调用instantiateBean实例化;

6.2.2如果之前没有解析过构造器:

 

6.2.2.1、通过SmartInstantiationAwareBeanPostProcessordetermineCandidateConstructors回调方法解析构造器,第二个BeanPostProcessor扩展点,返回第一个解析成功(返回值不为null)的构造器组,如AutowiredAnnotationBeanPostProcessor实现将自动扫描通过@Autowired/@Value注解的构造器从而可以完成构造器注入,请参考【第十二章】零配置 12.2 注解实现Bean依赖注入 ——跟我学spring3 

6.2.2.2autowireConstructor如果(6.2.2.1返回的不为null,且是有参构造器,调用autowireConstructor实例化;

6.2.2.3instantiateBean 否则调用无参构造器实例化;

 

7applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);第三个BeanPostProcessor扩展点,执行Bean定义的合并;

7.1、执行MergedBeanDefinitionPostProcessorpostProcessMergedBeanDefinition回调方法,进行bean定义的合并;

 

8addSingletonFactory(beanName, new ObjectFactory() {

                            public Object getObject() throws BeansException {

                                   return getEarlyBeanReference(beanName, mbd, bean);

                            }

                     });  及早暴露单例Bean引用,从而允许setter注入方式的循环引用

8.1SmartInstantiationAwareBeanPostProcessorgetEarlyBeanReference第四个BeanPostProcessor扩展点,当存在循环依赖时,通过该回调方法获取及早暴露的Bean实例;

 

9populateBean(beanName, mbd, instanceWrapper);装配Bean依赖

9.1InstantiationAwareBeanPostProcessorpostProcessAfterInstantiation第五个BeanPostProcessor扩展点,在实例化Bean之后,所有其他装配逻辑之前执行,如果false将阻止其他的InstantiationAwareBeanPostProcessorpostProcessAfterInstantiation的执行和从(9.2到(9.5的执行,通常返回true

9.2autowireByNameautowireByType根据名字和类型进行自动装配,自动装配的知识请参考【第三章】 DI 3.3 更多DI的知识 ——跟我学spring3  3.3.3  自动装配;

9.3InstantiationAwareBeanPostProcessorpostProcessPropertyValues第六个BeanPostProcessor扩展点,完成其他定制的一些依赖注入,如AutowiredAnnotationBeanPostProcessor执行@Autowired注解注入,CommonAnnotationBeanPostProcessor执行@Resource等注解的注入,PersistenceAnnotationBeanPostProcessor执行@ PersistenceContextJPA注解的注入,RequiredAnnotationBeanPostProcessor执行@ Required注解的检查等等,请参考【第十二章】零配置 12.2 注解实现Bean依赖注入 ——跟我学spring3

9.4checkDependencies依赖检查,请参考【第三章】 DI 3.3 更多DI的知识 ——跟我学spring3  3.3.4  依赖检查;

9.5applyPropertyValues应用明确的setter属性注入,请参考【第三章】 DI 3.1 DI的配置使用 ——跟我学spring3 

 

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

10.1invokeAwareMethodsBeanNameAwareBeanClassLoaderAwareBeanFactoryAware:调用一些Aware标识接口注入如BeanNameBeanFactory

10.2BeanPostProcessorpostProcessBeforeInitialization第七个扩展点,在调用初始化之前完成一些定制的初始化任务,如BeanValidationPostProcessor完成JSR-303 @Valid注解Bean验证,InitDestroyAnnotationBeanPostProcessor完成@PostConstruct注解的初始化方法调用,ApplicationContextAwareProcessor完成一些Aware接口的注入(如EnvironmentAwareResourceLoaderAwareApplicationContextAware,其返回值将替代原始的Bean对象

10.3invokeInitMethods 调用初始化方法;

10.3.1InitializingBeanafterPropertiesSet :调用InitializingBeanafterPropertiesSet回调方法;

10.3.2、通过xml指定的自定义init-method 调用通过xml配置的自定义init-method

10.3.3BeanPostProcessorpostProcessAfterInitialization 第八个扩展点,AspectJAwareAdvisorAutoProxyCreator(完成xml风格的AOP配置(<aop:config>)的目标对象包装到AOP代理对象)、AnnotationAwareAspectJAutoProxyCreator(完成@Aspectj注解风格(<aop:aspectj-autoproxy> @Aspect)的AOP配置的目标对象包装到AOP代理对象),其返回值将替代原始的Bean对象

 

11if (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事务处理时自我调用的解决方案及一些实现方式的风险);

 

12registerDisposableBeanIfNecessary(beanName, bean, mbd) 注册Bean的销毁方法(只有非原型Bean可注册);

12.1、单例Bean的销毁流程

12.1.1DestructionAwareBeanPostProcessorpostProcessBeforeDestruction 第九个扩展点,如InitDestroyAnnotationBeanPostProcessor完成@PreDestroy注解的销毁方法注册和调用;

12.1.2DisposableBeandestroy注册/调用DisposableBeandestroy销毁方法;

12.1.3、通过xml指定的自定义destroy-method 注册/调用通过XML指定的destroy-method销毁方法;

12.1.2ScoperegisterDestructionCallback注册自定义的Scope的销毁回调方法,如RequestScopeSessionScope等;其流程和【12.1 单例Bean的销毁流程一样】,关于自定义Scope请参考【第三章】 DI 3.4 Bean的作用域 ——跟我学spring3

 

13、到此Bean实例化、依赖注入、初始化完毕可以返回创建好的bean了。

 

 从上面的流程我们可以看到BeanPostProcessor一个使用了九个扩展点,其实还一个扩展点(SmartInstantiationAwareBeanPostProcessorpredictBeanType在下一篇介绍),接下来我们看看BeanPostProcessor这些扩展点都主要完成什么功能及常见的BeanPostProcessor

 

我将在下一帖子中使用例子来解析这八个扩展点的主要功能,及一些Spring默认提供的BeanPostProcessor主要作用。

 

欢迎大家一起探讨学习。

 

下一篇地址:Spring开闭原则的表现-BeanPostProcessor扩展点-2

  • 大小: 24.4 KB
   发表时间:2012-04-19  
beanPostProcesso为对象实例化前后提供了可扩展的空间,spring里面最典型的beanPostProcessor实现就是属性文件占位(PropertyPlaceholderConfigurer)。
0 请登录后投票
   发表时间:2012-04-19  
xiangdefei 写道
beanPostProcesso为对象实例化前后提供了可扩展的空间,spring里面最典型的beanPostProcessor实现就是属性文件占位(PropertyPlaceholderConfigurer)。

下一篇帖子详细介绍Spring内置的BeanPostProcessor 及其功能

AnnotationAwareAspectJAutoProxyCreator 
AspectJAwareAdvisorAutoProxyCreator 
InitDestroyAnnotationBeanPostProcessor
ApplicationContextAwareProcessor
AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
RequiredAnnotationBeanPostProcessor
PersistenceAnnotationBeanPostProcessor
等等…………
0 请登录后投票
   发表时间:2012-04-19  
LZ的好学的精神真值得学习,我工作了三年后都静不下来心去研究这些东西了。
0 请登录后投票
   发表时间:2012-04-19  
xiangdefei 写道
LZ的好学的精神真值得学习,我工作了三年后都静不下来心去研究这些东西了。

呵呵,营造个好的学习氛围,一起学习探讨 才有动力
0 请登录后投票
   发表时间:2012-04-19  
aop思想的延伸,参与bean创建事件,给用户一个修改bean的机会!!
0 请登录后投票
   发表时间:2012-04-19  
kjj 写道
aop思想的延伸,参与bean创建事件,给用户一个修改bean的机会!!

应该是Spring一直遵循的开闭原则,对扩展开放,对修改关闭。就如SpringMVC一样。提供很多扩展点
3 请登录后投票
   发表时间:2012-04-19  
xiangdefei 写道
beanPostProcesso为对象实例化前后提供了可扩展的空间,spring里面最典型的beanPostProcessor实现就是属性文件占位(PropertyPlaceholderConfigurer)。

PropertyPlaceholderConfigurer是 BeanFactoryPostProcessor 实现,是Bean工厂的后处理
0 请登录后投票
   发表时间:2012-04-20  
jinnianshilongnian 写道
kjj 写道
aop思想的延伸,参与bean创建事件,给用户一个修改bean的机会!!

应该是Spring一直遵循的开闭原则,对扩展开放,对修改关闭。就如SpringMVC一样。提供很多扩展点

你可以得到bean,对修改关闭,怎么理解,怎么个关闭法!!??
0 请登录后投票
   发表时间:2012-04-20  
kjj 写道
jinnianshilongnian 写道
kjj 写道
aop思想的延伸,参与bean创建事件,给用户一个修改bean的机会!!

应该是Spring一直遵循的开闭原则,对扩展开放,对修改关闭。就如SpringMVC一样。提供很多扩展点

你可以得到bean,对修改关闭,怎么理解,怎么个关闭法!!??

整体实例化、初始化、依赖装配是 流程的关闭
通过BeanPostProcessor进行扩展(如包装目标对象到AOP对象)
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics