BeanFactoryPostProcessor
各種Aware
BeanPostProcessor
隱藏的一些特殊功能
下文將一項(xiàng)一項(xiàng)地進(jìn)行梳理
BeanFactoryPostProcessor
簡介
BeanFactoryPostProcessor是一個(gè)很重要的接口,其中只有一個(gè)方法
voidpostProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)throwsBeansException;
它起作用的時(shí)機(jī)發(fā)生在解析成BeanDefinition后,實(shí)例化之前。從名字可以看出來,BeanFactoryPostProcessor針對的應(yīng)該是容器級別的擴(kuò)展,名為“BeanFactory PostProcessor”即對容器中所有的BeanDefinition都起普遍作用。BeanFactoryPostProcessor有幾個(gè)我們比較常用的子類PropertyPlaceholderConfigurer、CustomEditorConfigurer,前者用于配置文件中的${var}變量替換,后者用于自定義編輯BeanDefinition中的屬性值,合理利用CustomEditorConfigurer會有一些意想不到的效果(例如可以通過修改某些屬性實(shí)現(xiàn)類似aop的功能)。
使用
如果是在BeanFactory中使用,我們需要
PropertyPlaceholderConfigurer? configurer = new PropertyPlaceholderConfigurer();configurer.setLaction("xxx");configurer.postProcessBeanFactory(beanFactory);
很繁瑣,很麻煩,而且通常我們并不喜歡硬編碼直接使用BeanFactory。在ApplicationContext中得到了改善,使用BeanFactoryPostProcessor只需要在xml文件中進(jìn)行相應(yīng)的配置就行,因?yàn)锳pplicationContext在初始化過程中會調(diào)用invokeBeanFactoryPostProcessors(beanFactory),該函數(shù)會找出所有BeanFactoryPostProcessor類型的bean,調(diào)用postProcessBeanFactory方法。
BeanPostProcessor
簡介
BeanPostProcessor很容易和BeanFactoryPostProcessor混淆,但從名字上來說,BeanPostProcessor是“Bean PostProcessor”,主要針對于Bean這一級別,關(guān)注的主要是Bean實(shí)例化后,初始化前后的。為什么說主要呢?因?yàn)榇嬖谔乩幸粋€(gè)BeanPostProcessor的調(diào)用并不是發(fā)生在實(shí)例化后,初始化前后。BeanPostProcessor接口存在兩個(gè)方法,從名字可以看粗一個(gè)調(diào)用在初始化之前,一個(gè)調(diào)用在初始化之后。
ObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException;ObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException;
BeanPostProcessor在BeanFactory的初始化bean的函數(shù)initializeBean中,主要代碼為,基本就是取出所有的BeanPostProcessor,然后遍歷調(diào)用其postProcessBeforeInitialization或者postProcessAfterInitialization方法。
if(mbd ==null|| !mbd.isSynthetic()) {? ? ? ? ? ? wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);? ? ? ? }try{? ? ? ? ? ? invokeInitMethods(beanName, wrappedBean, mbd);? ? ? ? }catch(Throwable ex) {thrownewBeanCreationException(? ? ? ? ? ? ? ? ? ? (mbd !=null? mbd.getResourceDescription() :null),? ? ? ? ? ? ? ? ? ? beanName,"Invocation of init method failed", ex);? ? ? ? }if(mbd ==null|| !mbd.isSynthetic()) {? ? ? ? ? ? wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);? ? ? ? }publicObjectapplyBeanPostProcessorsBeforeInitialization(ObjectexistingBean,StringbeanName)throwsBeansException {Objectresult = existingBean;for(BeanPostProcessor beanProcessor : getBeanPostProcessors()) {? ? ? ? ? ? result = beanProcessor.postProcessBeforeInitialization(result, beanName);if(result ==null) {returnresult;? ? ? ? ? ? }? ? ? ? }returnresult;? ? }
使用
Spring利用BeanPostProcessor給了我們在bean初始化前后“doSomething”的機(jī)會。
在BeanFactory中使用需要編碼
beanFactory.addBeanPostProcessor(newSomeBeanPostProcessor);
但是在ApplicationContext中,我們只需要將自定義的BeanPostProcessor配置到xml文件中即可。ApplicationContext在初始化過程中會識別所有的BeanPostProcessors并添加到BeanFactory中。
各種Aware
簡介
這種類型的擴(kuò)展點(diǎn)是我們比較熟悉的了,例如ApplicationContextAware、BeanFactoryAware等,Aware的接口用于標(biāo)識“我需要這個(gè)對象”,例如ApplicationContextAware通知容器我需要“當(dāng)前的ApplicationContext對象”。這個(gè)Spring給我們提供的一種用于獲取有用對象的一種好的方式。
使用
需要注意的是,Aware起作用的時(shí)機(jī)是在Bean已經(jīng)完成實(shí)例化之后,初始化Bean的同時(shí)。而且需要注意的是BeanFactory對于Aware的處理和ApplicationContext是不同的。
先看BeanFactory中的處理方式,各種Aware被調(diào)用的地方是在初始化bean的函數(shù)
initializeBean中
protectedObjectinitializeBean(finalStringbeanName,finalObjectbean, RootBeanDefinition mbd) {if(System.getSecurityManager() !=null) {? ? ? ? ? ? AccessController.doPrivileged(newPrivilegedAction() {publicObjectrun() {? ? ? ? ? ? ? ? ? ? invokeAwareMethods(beanName, bean);returnnull;? ? ? ? ? ? ? ? }? ? ? ? ? ? }, getAccessControlContext());? ? ? ? }else{? ? ? ? ? ? invokeAwareMethods(beanName, bean);? ? ? ? }ObjectwrappedBean = bean;if(mbd ==null|| !mbd.isSynthetic()) {? ? ? ? ? ? wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);? ? ? ? }try{? ? ? ? ? ? invokeInitMethods(beanName, wrappedBean, mbd);? ? ? ? }catch(Throwable ex) {thrownewBeanCreationException(? ? ? ? ? ? ? ? ? ? (mbd !=null? mbd.getResourceDescription() :null),? ? ? ? ? ? ? ? ? ? beanName,"Invocation of init method failed", ex);? ? ? ? }if(mbd ==null|| !mbd.isSynthetic()) {? ? ? ? ? ? wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);? ? ? ? }returnwrappedBean;? ? }privatevoidinvokeAwareMethods(finalStringbeanName,finalObjectbean) {if(beaninstanceofAware) {if(beaninstanceofBeanNameAware) {? ? ? ? ? ? ? ? ((BeanNameAware) bean).setBeanName(beanName);? ? ? ? ? ? }if(beaninstanceofBeanClassLoaderAware) {? ? ? ? ? ? ? ? ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());? ? ? ? ? ? }if(beaninstanceofBeanFactoryAware) {? ? ? ? ? ? ? ? ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);? ? ? ? ? ? }? ? ? ? }? ? }
可以看到其發(fā)生在invokeInitMethods之前。而ApplicationContext怎么處理呢?ApplicationContext本身是利用BeanFactory進(jìn)行容器的初始化,而BeanFactory卻硬編碼了invokeAwareMethods中Aware的類型,那ApplicationContext究竟是怎么調(diào)用ApplicationContextAware的呢,答案就在函數(shù)prepareBeanFactory中,
beanFactory.addBeanPostProcessor(newApplicationContextAwareProcessor(this));
ApplicationContext為beanFactory增加了ApplicationContextAwareProcessor,ApplicationContextAwareProcessor是一種BeanPostProcessor。前文提到BeanPostProcessor發(fā)生在bean初始化前后,在bean初始化之前將調(diào)用postProcessBeforeInitialization方法,ApplicationContextAwareProcessor#postProcessBeforeInitialization如下:
publicObjectpostProcessBeforeInitialization(finalObjectbean,StringbeanName)throwsBeansException {? ? ? ? AccessControlContext acc =null;if(System.getSecurityManager() !=null&&? ? ? ? ? ? ? ? (beaninstanceofEnvironmentAware || beaninstanceofEmbeddedValueResolverAware ||? ? ? ? ? ? ? ? ? ? ? ? beaninstanceofResourceLoaderAware || beaninstanceofApplicationEventPublisherAware ||? ? ? ? ? ? ? ? ? ? ? ? beaninstanceofMessageSourceAware || beaninstanceofApplicationContextAware)) {? ? ? ? ? ? acc =this.applicationContext.getBeanFactory().getAccessControlContext();? ? ? ? }if(acc !=null) {? ? ? ? ? ? AccessController.doPrivileged(newPrivilegedAction() {publicObjectrun() {? ? ? ? ? ? ? ? ? ? invokeAwareInterfaces(bean);returnnull;? ? ? ? ? ? ? ? }? ? ? ? ? ? }, acc);? ? ? ? }else{? ? ? ? ? ? invokeAwareInterfaces(bean);? ? ? ? }returnbean;? ? }privatevoidinvokeAwareInterfaces(Objectbean) {if(beaninstanceofAware) {if(beaninstanceofEnvironmentAware) {? ? ? ? ? ? ? ? ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());? ? ? ? ? ? }if(beaninstanceofEmbeddedValueResolverAware) {? ? ? ? ? ? ? ? ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(newEmbeddedValueResolver(this.applicationContext.getBeanFactory()));? ? ? ? ? ? }if(beaninstanceofResourceLoaderAware) {? ? ? ? ? ? ? ? ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);? ? ? ? ? ? }if(beaninstanceofApplicationEventPublisherAware) {? ? ? ? ? ? ? ? ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);? ? ? ? ? ? }if(beaninstanceofMessageSourceAware) {? ? ? ? ? ? ? ? ((MessageSourceAware) bean).setMessageSource(this.applicationContext);? ? ? ? ? ? }if(beaninstanceofApplicationContextAware) {? ? ? ? ? ? ? ? ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);? ? ? ? ? ? }? ? ? ? }? ? }
可以看出ApplicationContext利用ApplicationContextAwareProcessor完成了ApplicationContext中特有的一些Aware的調(diào)用,發(fā)生的時(shí)機(jī)在初bean始化之前。
一種特殊的BeanPostProcessor-InstantiationAwareBeanPostProcessor
前文提到BeanPostProcessor主要作用于Bean實(shí)例化后,初始化前后,但是存在特例,InstantiationAwareBeanPostProcessor就是特例,其發(fā)生在Bean實(shí)例化前,
在真正調(diào)用doCreate()創(chuàng)建bean實(shí)例化之前,調(diào)用了resolveBeforeInstantiation進(jìn)行了短路操作,如果此方法返回值不為空則直接返回bean。spring注釋“Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. ”給BeanPostProcessors一個(gè)機(jī)會返回代理proxy對象。
try{? // GiveBeanPostProcessorsa chance to return a proxy instead of the targetbeaninstance.? Objectbean= resolveBeforeInstantiation(beanName,mbd);if(bean!= null) {? ? ? returnbean;}}? ? protected Object resolveBeforeInstantiation(StringbeanName,RootBeanDefinition mbd) {? ? ? ? Objectbean= null;if(!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)){? ? ? ? ? ? // Make surebeanclass is actually resolved at this point.if(mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {bean= applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(),beanName);if(bean!= null) {bean= applyBeanPostProcessorsAfterInitialization(bean,beanName);}? ? ? ? ? ? }? ? ? ? ? ? mbd.beforeInstantiationResolved= (bean!= null);}? ? ? ? returnbean;}
我們熟知的AOP,對target對象進(jìn)行代理就是實(shí)現(xiàn)了InstantiationAwareBeanPostProcessor接口,在Bean實(shí)例化之前短路操作返回代理Proxy對象。
ApplicationContext的事件發(fā)布
--待續(xù)
總結(jié)
本文總結(jié)了Spring容器中幾種使用較多的擴(kuò)展機(jī)制,Spring作為一個(gè)設(shè)計(jì)良好的框架,遵循了“對修改封閉,對擴(kuò)展開放”的原則,我們可以根據(jù)自己的實(shí)際需要來自定義BeanFactoryPostProcessor,BeanPostProcessor來在bean的生命周期里doSomething,實(shí)現(xiàn)各種Aware接口拿到容器中提供的一些有用對象,通過自定義監(jiān)聽器監(jiān)聽容器的事件等。