【Spring源碼】- 05 擴(kuò)展點(diǎn)之BeanPostProcessor

【Spring源碼】- 05 擴(kuò)展點(diǎn)之BeanPostProcessor

原創(chuàng)?張張?Reactor2020?昨天

原文鏈接:https://mp.weixin.qq.com/s?__biz=MzIxNjM0OTk3MQ==&mid=2247483769&idx=1&sn=7b0ad633d8e0741ecdacf4c498b32aca&chksm=978b2d05a0fca4132607289a51cdead9376a321f36cfb8f3aebebbcda156617585e8c61ca8f6&token=1573542807&lang=zh_CN#rd


類結(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ò)展。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容