【Spring源碼】- 05 擴(kuò)展點(diǎn)之BeanPostProcessor
原創(chuàng)?張張?Reactor2020?昨天

類結(jié)構(gòu)
BeanPostProcessor和BeanFactoryPostProcessor是Spring中兩個(gè)最重要的擴(kuò)展的。如果說(shuō)BeanFactoryPostProcessor是面向IoC進(jìn)行擴(kuò)展,BeanPostProcessor就是面向Bean進(jìn)行擴(kuò)展。
從上面類結(jié)構(gòu)圖可以看出,BeanPostProcessor是一個(gè)頂層接口,下面有衍生出幾個(gè)接口,實(shí)現(xiàn)對(duì)Bean創(chuàng)建、初始化等各個(gè)階段進(jìn)行更細(xì)化的擴(kuò)展,所以BeanPostProcessor要比BeanFactoryPostProcessor復(fù)雜一些,可以實(shí)現(xiàn)更多擴(kuò)展場(chǎng)景。
注冊(cè)順序
BeanPostProcessor被注冊(cè)到IoC中才能起作用,在refresh()方法中registerBeanPostProcessors(beanFactory);這一語(yǔ)句完成BeanPostProcessor的注冊(cè)工作,注冊(cè)使用:addBeanPostProcessor(BeanPostProcessor beanPostProcessor)方法完成。
注冊(cè)BeanPostProcessor也涉及到先后順序關(guān)系,大致邏輯總結(jié)如下:
1、獲取實(shí)現(xiàn)PriorityOrdered接口的BeanPostProcessor,然后通過(guò)getBean()方法實(shí)例化,排序后注冊(cè)到容器中;
2、獲取實(shí)現(xiàn)Ordered接口的BeanPostProcessor,然后通過(guò)getBean()方法實(shí)例化,排序后注冊(cè)到容器中;
3、獲取常規(guī)沒(méi)有實(shí)現(xiàn)PriorityOrdered和Ordered接口BeanPostProcessor,然后通過(guò)getBean()方法實(shí)例化,注冊(cè)到容器中;
4、上述步驟中MergedBeanDefinitionPostProcessor類型會(huì)單獨(dú)存儲(chǔ)到internalPostProcessors集合中,排序后保證放到末尾
5、最后移除ApplicationListenerDetector重新追加到最末尾
上面只是BeanPostProcessor注冊(cè)先后順序關(guān)系,并不會(huì)涉及到BeanPostProcessor的執(zhí)行,由于BeanPostProcessor擴(kuò)展出幾個(gè)子類,下面我們來(lái)分析下每個(gè)子類的執(zhí)行時(shí)機(jī)。
BeanPostProcessor
執(zhí)行時(shí)機(jī)
接口定義見(jiàn)下:
publicinterfaceBeanPostProcessor{
@Nullable
defaultObjectpostProcessBeforeInitialization(Object?bean,?String?beanName)throwsBeansException{
returnbean;
}
@Nullable
defaultObjectpostProcessAfterInitialization(Object?bean,?String?beanName)throwsBeansException{
returnbean;
}
}
之前分析IoC容器啟動(dòng)流程時(shí),介紹過(guò)initializeBean()方法完成Bean的init-method初始化工作,BeanPostProcessor就是在init-method執(zhí)行前后進(jìn)行擴(kuò)展。
protectedObjectinitializeBean(finalString?beanName,finalObject?bean,?@Nullable?RootBeanDefinition?mbd){
Object?wrappedBean?=?bean;
if(mbd?==null||?!mbd.isSynthetic())?{
//觸發(fā)BeanPostProcessor#postProcessBeforeInitialization()方法執(zhí)行
wrappedBean?=?applyBeanPostProcessorsBeforeInitialization(wrappedBean,?beanName);
}
//執(zhí)行init-method方法
invokeInitMethods(beanName,?wrappedBean,?mbd);
if(mbd?==null||?!mbd.isSynthetic())?{
//觸發(fā)BeanPostProcessor#postProcessAfterInitialization()方法執(zhí)行
wrappedBean?=?applyBeanPostProcessorsAfterInitialization(wrappedBean,?beanName);
}
returnwrappedBean;
}
再來(lái)看下這兩個(gè)方法的調(diào)用邏輯:
publicObjectapplyBeanPostProcessorsBeforeInitialization(Object?existingBean,?String?beanName)
throwsBeansException
{
Object?result?=?existingBean;
for(BeanPostProcessor?processor?:?getBeanPostProcessors())?{
Object?current?=?processor.postProcessBeforeInitialization(result,?beanName);
if(current?==null)?{
returnresult;
}
result?=?current;
}
returnresult;
}
如果有postProcessBeforeInitialization()方法返回null,則表示該擴(kuò)展點(diǎn)提前結(jié)束,不再需要繼續(xù)執(zhí)行后續(xù)BeanPostProcessor的postProcessBeforeInitialization方法。
再來(lái)看下postProcessAfterInitialization()方法執(zhí)行邏輯是一樣的:
@Override
publicObjectapplyBeanPostProcessorsAfterInitialization(Object?existingBean,?String?beanName)
throwsBeansException
{
Object?result?=?existingBean;
for(BeanPostProcessor?processor?:?getBeanPostProcessors())?{
Object?current?=?processor.postProcessAfterInitialization(result,?beanName);
if(current?==null)?{
returnresult;
}
result?=?current;
}
returnresult;
}
使用場(chǎng)景
invokeInitMethods(beanName, wrappedBean, mbd);方法執(zhí)行Bean的init-method方法進(jìn)行初始化,進(jìn)入這個(gè)方法可以發(fā)現(xiàn),這里只會(huì)執(zhí)行實(shí)現(xiàn)InitializingBean和@Bean(initMethod="xxx")這兩種方式設(shè)置的init-method方法,我們平時(shí)使用很多的@PostConstruct注解方式,其實(shí)是通過(guò)InitDestroyAnnotationBeanPostProcessor這個(gè)擴(kuò)展類實(shí)現(xiàn):
InitDestroyAnnotationBeanPostProcessor類實(shí)現(xiàn)了DestructionAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor這兩個(gè)接口,間接方式繼承BeanPostProcessor。InitDestroyAnnotationBeanPostProcessor就是在postProcessBeforeInitialization()方法中完成了對(duì)@PostConstruct注解方法的調(diào)用,所以其執(zhí)行優(yōu)先級(jí)比InitializingBean和@Bean(initMethod="xxx")這兩種方式更加靠前。
如果你需要在init-method等Bean的初始化執(zhí)行前后進(jìn)行擴(kuò)展,可以使用此接口實(shí)現(xiàn)。比如:判斷Bean是否是線程池類,如果是則統(tǒng)一設(shè)置管理的線程名前綴:
publicObjectpostProcessBeforeInitialization(Object?bean,?String?beanName)throwsBeansException{
if(beaninstanceofThreadPoolTaskExecutor)?{
((ThreadPoolTaskExecutor)?bean).setThreadNamePrefix("Post-");
}
returnbean;
}
還比如ApplicationListenerDetector在postProcessAfterInitialization()方法中實(shí)現(xiàn)將ApplicationListener類型的單例Bean注冊(cè)到事件多播器上,實(shí)現(xiàn)對(duì)事件的監(jiān)聽(tīng):
publicObjectpostProcessAfterInitialization(Object?bean,?String?beanName){
if(beaninstanceofApplicationListener)?{
Boolean?flag?=this.singletonNames.get(beanName);
if(Boolean.TRUE.equals(flag))?{
//?如果當(dāng)前?ApplicationListener?bean?scope?是?singleton?單例模式,則將它注冊(cè)到應(yīng)用的事件多播器上
this.applicationContext.addApplicationListener((ApplicationListener)?bean);
}
elseif(Boolean.FALSE.equals(flag))?{
//?如果ApplicationListener?bean?scope?不是?singleton?單例模式,則嘗試輸出警告日志,說(shuō)明情況,并移除
//所以ApplicationListener類型的只能是單例模式才會(huì)起作用
this.singletonNames.remove(beanName);
}
}
returnbean;
}
還比如ApplicationContextAwareProcessor這個(gè)就是在postProcessBeforeInitialization()方法中實(shí)現(xiàn)如ApplicationContextAware、EnvironmentAware等*Aware接口注入功能。實(shí)現(xiàn)原理非常簡(jiǎn)單,就是判斷Bean是否實(shí)現(xiàn)接口,然后通過(guò)setter方式注入即可:
privatevoidinvokeAwareInterfaces(Object?bean){
if(beaninstanceofEnvironmentAware)?{
((EnvironmentAware)?bean).setEnvironment(this.applicationContext.getEnvironment());
}
if(beaninstanceofEmbeddedValueResolverAware)?{
((EmbeddedValueResolverAware)?bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
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);
}
}
InstantiationAwareBeanPostProcessor
前面分析BeanPostProcessor接口是在Bean的init-method方法執(zhí)行前后進(jìn)行擴(kuò)展,其子接口InstantiationAwareBeanPostProcessor則可以在Bean的創(chuàng)建前后進(jìn)行擴(kuò)展,所以此擴(kuò)展比BeanPostProcessor擴(kuò)展更靠前。
接口定義見(jiàn)下:
publicinterfaceInstantiationAwareBeanPostProcessorextendsBeanPostProcessor{
//Bean創(chuàng)建之前回調(diào)該方法,beanClass就是將要被創(chuàng)建的Bean對(duì)應(yīng)的Class信息
@Nullable
defaultObjectpostProcessBeforeInstantiation(Class<?>?beanClass,?String?beanName)throwsBeansException{
returnnull;
}
//Bean創(chuàng)建之后回調(diào)該方法,參數(shù)bean就是創(chuàng)建完成的Bean對(duì)象
defaultbooleanpostProcessAfterInstantiation(Object?bean,?String?beanName)throwsBeansException{
returntrue;
}
//postProcessProperties()方法在postProcessAfterInstantiation()方法之后緊挨著執(zhí)行,其提供PropertyValues類型入?yún)?,所以在該方法中可以?shí)現(xiàn)依賴操作
@Nullable
defaultPropertyValuespostProcessProperties(PropertyValues?pvs,?Object?bean,?String?beanName)
throwsBeansException
{
returnnull;
}
//這個(gè)方法標(biāo)注@Deprecated已經(jīng)被廢棄了,被postProcessProperties()方法取代了
@Deprecated
@Nullable
defaultPropertyValuespostProcessPropertyValues(
PropertyValues?pvs,?PropertyDescriptor[]?pds,?Object?bean,?String?beanName)
throwsBeansException{
returnpvs;
}
}
createBean()方法中Object bean = resolveBeforeInstantiation(beanName, mbdToUse);這條語(yǔ)句中會(huì)觸發(fā)對(duì)postProcessBeforeInstantiation()方法的執(zhí)行。
protectedObjectcreateBean(String?beanName,?RootBeanDefinition?mbd,?@Nullable?Object[]?args)
throwsBeanCreationException
{
Object?bean?=?resolveBeforeInstantiation(beanName,?mbdToUse);//觸發(fā)對(duì)postProcessBeforeInstantiation()方法的執(zhí)行
if(bean?!=null)?{
returnbean;
}
...
Object?beanInstance?=?doCreateBean(beanName,?mbdToUse,?args);//創(chuàng)建Bean實(shí)例(一般真正創(chuàng)建Bean的方法)
...
}
InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()方法有個(gè)重要特性:如果該方法返回非null結(jié)果,則表示Bean提前創(chuàng)建完成,同時(shí)也會(huì)忽略掉后續(xù)的依賴注入、init-method初始化等步驟執(zhí)行,最后只需要執(zhí)行下BeanPostProcessor#postProcessAfterInitialization這個(gè)方法則整個(gè)Bean的創(chuàng)建流程就全部完成。
總結(jié):在創(chuàng)建對(duì)象之前調(diào)用了postProcessBeforeInstantiation方法可以實(shí)現(xiàn)給擴(kuò)展點(diǎn)一次創(chuàng)建代理的機(jī)會(huì),如果代理對(duì)象返回不為空則不再繼續(xù)常規(guī)方式創(chuàng)建Bean。
我們?cè)賮?lái)看下InstantiationAwareBeanPostProcessor接口中定義的另兩個(gè)方法執(zhí)行時(shí)機(jī),Bean創(chuàng)建完成后會(huì)執(zhí)行populateBean()進(jìn)行依賴注入,它們就是在這個(gè)方法中進(jìn)行觸發(fā)回調(diào),pupulateBean()方法大致見(jiàn)下:
protectedvoidpopulateBean(String?beanName,?RootBeanDefinition?mbd,?@Nullable?BeanWrapper?bw){
//執(zhí)行InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation方法回調(diào)
if(!mbd.isSynthetic()?&&?hasInstantiationAwareBeanPostProcessors())?{
for(BeanPostProcessor?bp?:?getBeanPostProcessors())?{
if(bpinstanceofInstantiationAwareBeanPostProcessor)?{
InstantiationAwareBeanPostProcessor?ibp?=?(InstantiationAwareBeanPostProcessor)?bp;
if(!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(),?beanName))?{
return;
}
}
}
}
//?注解注入:后置處理器ibp#postProcessProperties,大名鼎鼎的@Autowired就是在這處理的。
PropertyDescriptor[]?filteredPds?=null;
if(hasInstAwareBpps)?{
//執(zhí)行InstantiationAwareBeanPostProcessor#postProcessProperties方法回調(diào)
for(BeanPostProcessor?bp?:?getBeanPostProcessors())?{
if(bpinstanceofInstantiationAwareBeanPostProcessor)?{
InstantiationAwareBeanPostProcessor?ibp?=?(InstantiationAwareBeanPostProcessor)?bp;
PropertyValues?pvsToUse?=?ibp.postProcessProperties(pvs,?bw.getWrappedInstance(),?beanName);
if(pvsToUse?==null)?{
if(filteredPds?==null)?{
//獲取出對(duì)象的所有set?get方法,現(xiàn)在是有一個(gè)?getClass()方法,因?yàn)槔^承了Object,?沒(méi)什么其他卵用
filteredPds?=?filterPropertyDescriptorsForDependencyCheck(bw,?mbd.allowCaching);
}
//postProcessPropertyValues方法已廢棄,被postProcessProperties替代
pvsToUse?=?ibp.postProcessPropertyValues(pvs,?filteredPds,?bw.getWrappedInstance(),?beanName);
if(pvsToUse?==null)?{
return;
}
}
pvs?=?pvsToUse;
}
}
}
if(pvs?!=null)?{
applyPropertyValues(beanName,?mbd,?bw,?pvs);
}
}
上面代碼翻譯下大概就是:先執(zhí)行InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation方法回調(diào),然后再去執(zhí)行InstantiationAwareBeanPostProcessor#postProcessProperties,最后再去執(zhí)行applyPropertyValues()完成PropertyValue方式的依賴注入。這里有個(gè)大名鼎鼎的@Autowired、@Value方式的依賴注入,就是借助于InstantiationAwareBeanPostProcessor#postProcessProperties()方法實(shí)現(xiàn),這個(gè)實(shí)現(xiàn)類就是:AutowiredAnnotationBeanPostProcessor,簡(jiǎn)單看下依賴注入邏輯:
publicPropertyValuespostProcessProperties(PropertyValues?pvs,?Object?bean,?String?beanName){
/**
*?從緩存中找到此類的@Autowired、@Value注解元數(shù)據(jù),嘗試注入
* InjectionMetadata,持有待注入的元數(shù)據(jù)信息,執(zhí)行inject()方法,開(kāi)始注入屬性或方法參數(shù)。
*/
InjectionMetadata?metadata?=?findAutowiringMetadata(beanName,?bean.getClass(),?pvs);
try{
//為beanName填充上屬性bean
metadata.inject(bean,?beanName,?pvs);
}
catch(BeanCreationException?ex)?{
throwex;
}
catch(Throwable?ex)?{
thrownewBeanCreationException(beanName,"Injection?of?autowired?dependencies?failed",?ex);
}
returnpvs;
}
這里有意義的代碼就兩行:
1、InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);獲取Bean中需要依賴注入注入的元素,封裝成一個(gè)InjectionMetadata對(duì)象,該對(duì)象有兩個(gè)重要屬性:
targetClass指定目標(biāo)對(duì)象的Class;
Collection<InjectedElement> injectedElements:目標(biāo)對(duì)象中每個(gè)需要依賴注入的元素都會(huì)封裝成一個(gè)InjectedElement,然后存儲(chǔ)到該集合中。根據(jù)@Autowired/@Value注解到字段上還是方法上,InjectedElement又可以分為兩類:AutowiredFieldElement和AutowiredMethodElement。
2、metadata.inject(bean, beanName, pvs);:這個(gè)方法內(nèi)部就是循環(huán),對(duì)每個(gè)依賴元素InjectedElement調(diào)用inject()方法
if(!elementsToIterate.isEmpty())?{
for(InjectedElement?element?:?elementsToIterate)?{
if(logger.isTraceEnabled())?{
logger.trace("Processing?injected?element?of?bean?'"+?beanName?+"':?"+?element);
}
element.inject(target,?beanName,?pvs);
}
}
比如我們一般將@Autowired標(biāo)注到字段上,則這里會(huì)觸發(fā)AutowiredFieldElement#inject()方法執(zhí)行:
protectedvoidinject(Object?bean,?@Nullable?String?beanName,?@Nullable?PropertyValues?pvs)throwsThrowable{
Field?field?=?(Field)this.member;//依賴注入字段
Object?value;//存儲(chǔ)需要注入的值
if(this.cached)?{//如果已被緩存,則直接先從緩存中獲取依賴注入值
value?=?resolvedCachedArgument(beanName,this.cachedFieldValue);
}
else{//還未被緩存過(guò)
//1.DependencyDescriptor:用于對(duì)該依賴注入描述信息
DependencyDescriptor?desc?=newDependencyDescriptor(field,this.required);
desc.setContainingClass(bean.getClass());
Set?autowiredBeanNames?=newLinkedHashSet<>(1);
Assert.state(beanFactory?!=null,"No?BeanFactory?available");
TypeConverter?typeConverter?=?beanFactory.getTypeConverter();
try{
/*
2.查找依賴注入的值
比如:
@Autowired
private?TestService03?testService03;
這個(gè)value就是從IoC容器中查找到的TestService03對(duì)象
還比如:@Value("${spring.name}"),這個(gè)value就是從Spring上下文環(huán)境變量中解析出的spring.name變量值
*/
value?=?beanFactory.resolveDependency(desc,?beanName,?autowiredBeanNames,?typeConverter);
}
catch(BeansException?ex)?{
thrownewUnsatisfiedDependencyException(null,?beanName,newInjectionPoint(field),?ex);
}
//3.下面synchronized塊主要實(shí)現(xiàn)緩存功能,已被解析過(guò)的包裝成ShortcutDependencyDescriptor類型,上面resolvedCachedArgument對(duì)這種類型會(huì)特殊處理
synchronized(this)?{
if(!this.cached)?{
if(value?!=null||this.required)?{
this.cachedFieldValue?=?desc;
registerDependentBeans(beanName,?autowiredBeanNames);
if(autowiredBeanNames.size()?==1)?{
String?autowiredBeanName?=?autowiredBeanNames.iterator().next();
if(beanFactory.containsBean(autowiredBeanName)?&&
beanFactory.isTypeMatch(autowiredBeanName,?field.getType()))?{
this.cachedFieldValue?=newShortcutDependencyDescriptor(
desc,?autowiredBeanName,?field.getType());
}
}
}
else{
this.cachedFieldValue?=null;
}
this.cached?=true;
}
}
}
//4.查找到的依賴值不為null,則使用反射方式注入,因?yàn)槭峭ㄟ^(guò)反射方式,所以@Autowired、@Value是不需要setter/getter方法也可以注入
if(value?!=null)?{
//通過(guò)反射方式將查找到的需要依賴注入的值設(shè)置到對(duì)象實(shí)例中
ReflectionUtils.makeAccessible(field);
field.set(bean,?value);
}
}
SmartInstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor還有個(gè)子接口:SmartInstantiationAwareBeanPostProcessor,其定義如下:
publicinterfaceSmartInstantiationAwareBeanPostProcessorextendsInstantiationAwareBeanPostProcessor{
//推斷類型
@Nullable
defaultClass?predictBeanType(Class?beanClass,?String?beanName)throwsBeansException?{
returnnull;
}
//根據(jù)一定規(guī)則推斷出Bean中優(yōu)選的構(gòu)造方法
@Nullable
defaultConstructor[]?determineCandidateConstructors(Class?beanClass,?String?beanName)
throwsBeansException?{
returnnull;
}
defaultObjectgetEarlyBeanReference(Object?bean,?String?beanName)throwsBeansException{
returnbean;
}
}
SmartInstantiationAwareBeanPostProcessor接口有三個(gè)方法,在實(shí)例創(chuàng)建前智能判斷實(shí)例類型、智能判斷構(gòu)造函數(shù)、提起獲取暴露Bean引用,該接口主要是spring框架內(nèi)部使用,開(kāi)發(fā)時(shí)很少去擴(kuò)展該接口。
這里主要注意第三個(gè)方法:getEarlyBeanReference(),這個(gè)擴(kuò)展方法主要與Spring中的循環(huán)依賴有關(guān)系。前面分析IoC容器啟動(dòng)時(shí)分析過(guò):為了解決Spring中的循環(huán)依賴問(wèn)題,在doCreateBean()方法內(nèi)部,會(huì)將剛創(chuàng)建還未來(lái)得及進(jìn)行依賴注入和初始化的半成品Bean提前暴露出去,addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));,注意這里不是直接將Bean暴露出去,而是通過(guò)() -> getEarlyBeanReference(beanName, mbd, bean)這句將Bean包裝成ObjectFactory類型再暴露出去。
這里的一個(gè)核心就是:為什么不直接暴露Bean,而是將Bean包裝成ObjectFactory再去暴露?將Bean包裝成ObjectFactory再去暴露,調(diào)用getObject()方法時(shí)會(huì)觸發(fā)SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference方法回調(diào)。
分析到這里,還不夠完善,因?yàn)槟憧赡軙?huì)問(wèn):那這個(gè)方法回調(diào)又可以給我們解決什么問(wèn)題呢?
可以利用Spring AOP原理來(lái)回答這個(gè)問(wèn)題,Spring AOP主要基于AnnotationAwareAspectJAutoProxyCreator這個(gè)類實(shí)現(xiàn),這個(gè)類實(shí)現(xiàn)了BeanPostProcessor接口,在postProcessAfterInitialization()方法中對(duì)創(chuàng)建完成的Bean采用動(dòng)態(tài)代理方式將增強(qiáng)邏輯織入進(jìn)去。
如果存在這樣情況:A依賴B,B同時(shí)依賴A,這就是所說(shuō)的Spring循環(huán)依賴,但是如果我們對(duì)A采用了AOP增強(qiáng),這個(gè)過(guò)程會(huì)是怎樣情況呢?
A對(duì)象創(chuàng)建完成后,由于可能會(huì)存在循環(huán)依賴問(wèn)題,所以Spring會(huì)提前將A暴露出去;
然后對(duì)A進(jìn)行依賴注入,發(fā)現(xiàn)A依賴B,然后A就卡主了,通過(guò)getBean(B)獲取B實(shí)例時(shí),這時(shí)就會(huì)進(jìn)入B對(duì)象創(chuàng)建流程;
同樣B對(duì)象創(chuàng)建完成后并將B對(duì)象提前暴露出去,然后開(kāi)始執(zhí)行B對(duì)象的依賴注入,通過(guò)getBean(A)方式獲取,因?yàn)锳已經(jīng)提前暴露出去了,所以獲取A是沒(méi)問(wèn)題的;
然后B順利執(zhí)行完依賴注入、init-method初始化工作,則B整個(gè)創(chuàng)建流程全部完成;
這時(shí)A中通過(guò)getBean(B)方法就可以返回B對(duì)象,然后依賴注入到A中,然后執(zhí)行init-method初始化;
由于A是有AOP攔截的,在執(zhí)行完init-method初始化方法后,postProcessAfterInitialization()執(zhí)行時(shí)會(huì)給A通過(guò)動(dòng)態(tài)代理方式織入增強(qiáng)邏輯;
這時(shí),步驟3中給B注入的是A的原生對(duì)象,但是步驟6會(huì)給A創(chuàng)建一個(gè)代理對(duì)象,但是B中這時(shí)還是原生對(duì)象沒(méi)法改變,這就會(huì)導(dǎo)致有的依賴注入的是原生對(duì)象,有的依賴注入的是代理對(duì)象,會(huì)出現(xiàn)錯(cuò)亂問(wèn)題。如何解決呢?這個(gè)就是SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference這個(gè)擴(kuò)展點(diǎn)作用。
A對(duì)象提前暴露時(shí),利用ObjectFactory包裝了一層,B對(duì)象在進(jìn)行依賴注入時(shí)獲取到對(duì)象A時(shí),不是直接返回A,而是觸發(fā)getEarlyBeanReference()方法執(zhí)行,AnnotationAwareAspectJAutoProxyCreator類在getEarlyBeanReference()方法中實(shí)現(xiàn)判斷A需要做動(dòng)態(tài)代理,則對(duì)A進(jìn)行動(dòng)態(tài)代理后返回,這時(shí)B中依賴注入的就不是原生對(duì)象。
總結(jié):SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference()方法是在循環(huán)依賴場(chǎng)景下,對(duì)提前暴露的Bean可以通過(guò)該擴(kuò)展點(diǎn)進(jìn)行處理。只有因?yàn)榇嬖谘h(huán)依賴,才會(huì)導(dǎo)致需要需要獲取那些提前暴露的Bean時(shí)才會(huì)觸發(fā)該擴(kuò)展點(diǎn),所以,理解這個(gè)擴(kuò)展點(diǎn)關(guān)鍵在于你對(duì)Spring循環(huán)依賴的理解。
DestructionAwareBeanPostProcessor
DestructionAwareBeanPostProcessor是BeanPostProcessor子接口,其定義如下:
publicinterfaceDestructionAwareBeanPostProcessorextendsBeanPostProcessor{
//Bean銷毀前回調(diào)方法
voidpostProcessBeforeDestruction(Object?bean,?String?beanName)throwsBeansException;
//可以根據(jù)Bean進(jìn)行過(guò)濾,哪些Bean需要用到當(dāng)前這個(gè)回調(diào)
defaultbooleanrequiresDestruction(Object?bean){
returntrue;
}
}
從名稱就可以看出,該擴(kuò)展主要用于Bean銷毀之前,回調(diào)時(shí)機(jī)在:DisposableBeanAdapter#destroy()
publicvoiddestroy(){
//調(diào)用DestructionAwareBeanPostProcessor#postProcessBeforeDestruction,Bean銷毀之前回調(diào)接口
if(!CollectionUtils.isEmpty(this.beanPostProcessors))?{
for(DestructionAwareBeanPostProcessor?processor?:this.beanPostProcessors)?{
processor.postProcessBeforeDestruction(this.bean,this.beanName);
}
}
...
((DisposableBean)this.bean).destroy();//調(diào)用DisposableBean.destroy()
...
}
DestructionAwareBeanPostProcessor接口有個(gè)實(shí)現(xiàn)類InitDestroyAnnotationBeanPostProcessor,實(shí)現(xiàn)對(duì)@PreDestroy注解支持。該擴(kuò)展接口本身是比較簡(jiǎn)單的,后續(xù)分析Bean生命周期destroy流程整體梳理。
MergedBeanDefinitionPostProcessor
MergedBeanDefinitionPostProcessor
publicinterfaceMergedBeanDefinitionPostProcessorextendsBeanPostProcessor{
voidpostProcessMergedBeanDefinition(RootBeanDefinition?beanDefinition,?Class<?>?beanType,?String?beanName);
//Spring5.1新增接口,實(shí)現(xiàn)BeanDefinition重置通知,一般該方法實(shí)現(xiàn)重置前清理metadata等元數(shù)據(jù)緩存
defaultvoidresetBeanDefinition(String?beanName){
}
}
我們主要看下postProcessMergedBeanDefinition()方法調(diào)用時(shí)機(jī):
protectedObjectdoCreateBean(finalString?beanName,finalRootBeanDefinition?mbd,final@Nullable?Object[]?args)
throwsBeanCreationException
{
//1.創(chuàng)建對(duì)象
//2.執(zhí)行MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition回調(diào)方法
synchronized(mbd.postProcessingLock)?{
if(!mbd.postProcessed)?{
applyMergedBeanDefinitionPostProcessors(mbd,?beanType,?beanName);
mbd.postProcessed?=true;
}
}
//3.提前暴露Bean
//4.populateBean(beanName,?mbd,?instanceWrapper);
//5.exposedObject?=?initializeBean(beanName,?exposedObject,?mbd);
}
MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition發(fā)生在Bean剛創(chuàng)建完成,Bean還未提前暴露之前。MergedBeanDefinitionPostProcessor在Spring中有很多的應(yīng)用,比如:AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、InitDestroyAnnotationBeanPostProcessor等。這個(gè)擴(kuò)展的一般套路是和其它擴(kuò)展點(diǎn)一起使用,其起到一個(gè)幫手角色,postProcessMergedBeanDefinition將需要處理的注解信息解析成元數(shù)據(jù)信息緩存起來(lái),其它擴(kuò)展點(diǎn)就可以從緩存中獲取需要處理的注解信息進(jìn)行處理。有關(guān)這擴(kuò)展點(diǎn)更多的情況會(huì)在后續(xù)案例分析中再詳細(xì)分析。
總結(jié)
BeanFactoryPostProcessor和BeanPostProcessor是Spring提供的兩個(gè)最核心、最基礎(chǔ)的擴(kuò)展方式:一個(gè)面向IoC進(jìn)行擴(kuò)展,另一個(gè)面向Bean的創(chuàng)建流程進(jìn)行各種擴(kuò)展。BeanPostProcessor及其子類實(shí)現(xiàn)了對(duì)Bean創(chuàng)建過(guò)程中的各種擴(kuò)展:Bean創(chuàng)建前后、Bean初始化前后、獲取提前暴露對(duì)象前等等這些。Spring中大量注解簡(jiǎn)化了我們使用框架的復(fù)雜性,而這些注解很大一部分就是基于這些擴(kuò)展進(jìn)行處理,學(xué)習(xí)這些擴(kuò)展點(diǎn)可以幫助我們更好的熟悉Spring的運(yùn)行機(jī)理,同時(shí)可以在開(kāi)發(fā)中幫助我們靈活的實(shí)現(xiàn)各種功能擴(kuò)展。