你知道Spring是怎么將AOP應用到Bean的生命周期中的嗎?

”
在上篇文章中(Spring中AOP相關的API及源碼解析,原來AOP是這樣子的)我們已經分析過了AOP的實現(xiàn)的源碼,那么Spring是如何將AOP應用到Bean的生命周期的呢?這篇文章就帶著大家來探究下這個問題。本文我們要分析的代碼還是位于org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean這個方法中,在《我們來談一談Spring中的屬性注入 》這篇文章中,我們已經分析過了populateBean這個方法,

所以本文我們接著來看看initializeBean這個方法,它主要干了這么幾件事
執(zhí)行 Aware接口中的方法執(zhí)行 生命周期回調方法完成 AOP代理
對應源碼如下:
protected?Object?initializeBean(String?beanName,?Object?bean,?@Nullable?RootBeanDefinition?mbd)?{
??if?(System.getSecurityManager()?!=?null)?{
???AccessController.doPrivileged((PrivilegedAction因為在Spring官網(wǎng)閱讀(九)Spring中Bean的生命周期(上)文章中我們已經對這個方法做過分析了,并且這個方法本身也比較簡單,所以不再對這個方法做過多贅述,我們主要關注的就是Spring是如何將AOP應用到Bean的生命周期中的,對應的就是applyBeanPostProcessorsAfterInitialization這個方法,其源碼如下:
public?Object?applyBeanPostProcessorsAfterInitialization(Object?existingBean,?String?beanName)
????throws?BeansException?{
????Object?result?=?existingBean;
????for?(BeanPostProcessor?processor?:?getBeanPostProcessors())?{
????????Object?current?=?processor.postProcessAfterInitialization(result,?beanName);
????????if?(current?==?null)?{
????????????return?result;
????????}
????????result?=?current;
????}
????return?result;
}
實際上就是調用了所有后置處理器的postProcessAfterInitialization方法,在Spring中AOP相關的API及源碼解析,原來AOP是這樣子的一文中已經提到過了,@EnableAspectJAutoProxy注解實際上就是向容器中注冊了一個AnnotationAwareAspectJAutoProxyCreator,這個類本身就是一個后置處理器,AOP代理就是由它在這一步完成的。
Bean生命周期中AOP的流程
1、@EnableAspectJAutoProxy
通過@EnableAspectJAutoProxy注解向容器中注冊一個AnnotationAwareAspectJAutoProxyCreator的BeanDefinition,它本身也是一個BeanPostProcessor,這個BeanDefinition會在org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors這個方法中完成創(chuàng)建,如下圖所示

2、postProcessBeforeInstantiation方法執(zhí)行
執(zhí)行AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation方法,實際上就是父類AbstractAutoProxyCreator的postProcessBeforeInstantiation被執(zhí)行
對應源碼如下:
//??這個方法的主要目的就是在不考慮通知的情況下,確認哪些Bean不需要被代理
//??1.Advice,Advisor,Pointcut類型的Bean不需要被代理
//??2.不是原始Bean被包裝過的Bean不需要被代理,例如ScopedProxyFactoryBean
//??實際上并不只是這些Bean不需要被代理,如果沒有對應的通知需要被應用到這個Bean上的話
//??這個Bean也是不需要被代理的,只不過不是在這個方法中處理的。
public?Object?postProcessBeforeInstantiation(Class>?beanClass,?String?beanName)?{
????Object?cacheKey?=?getCacheKey(beanClass,?beanName);
????//?如果beanName為空或者為這個bean提供了定制的targetSource
????if?(!StringUtils.hasLength(beanName)?||?!this.targetSourcedBeans.contains(beanName))?{
????????//?advisedBeans是一個map,其中key是BeanName,value代表了這個Bean是否需要被代理
????????//?如果已經包含了這個key,不需要在進行判斷了,直接返回即可
????????//?因為這個方法的目的就是在實例化前就確認哪些Bean是不需要進行AOP的
????????if?(this.advisedBeans.containsKey(cacheKey))?{
????????????return?null;
????????}
????????//?說明還沒有對這個Bean進行處理
????????//?在這里會對SpringAOP中的基礎設施bean,例如Advice,Pointcut,Advisor做標記
????????//?標志它們不需要被代理,對應的就是將其放入到advisedBeans中,value設置為false
????????//?其次,如果這個Bean不是最原始的Bean,那么也不進行代理,也將其value設置為false
????????if?(isInfrastructureClass(beanClass)?||?shouldSkip(beanClass,?beanName))?{
????????????this.advisedBeans.put(cacheKey,?Boolean.FALSE);
????????????return?null;
????????}
????}
????//?是否為這個Bean提供了定制的TargetSource
????//?如果提供了定制的TargetSource,那么直接在這一步創(chuàng)建一個代理對象并返回
????//?一般不會提供
????TargetSource?targetSource?=?getCustomTargetSource(beanClass,?beanName);
????if?(targetSource?!=?null)?{
????????if?(StringUtils.hasLength(beanName))?{
????????????this.targetSourcedBeans.add(beanName);
????????}
????????Object[]?specificInterceptors?=?getAdvicesAndAdvisorsForBean(beanClass,?beanName,?targetSource);
????????Object?proxy?=?createProxy(beanClass,?beanName,?specificInterceptors,?targetSource);
????????this.proxyTypes.put(cacheKey,?proxy.getClass());
????????return?proxy;
????}
????return?null;
}
3、postProcessAfterInitialization方法執(zhí)行
實際上也是執(zhí)行父類AbstractAutoProxyCreator中的方法,對應源碼如下:
public?Object?postProcessAfterInitialization(@Nullable?Object?bean,?String?beanName)?{
????if?(bean?!=?null)?{
????????Object?cacheKey?=?getCacheKey(bean.getClass(),?beanName);
????????//?什么時候這個判斷會成立呢?
????????//?如果不出現(xiàn)循環(huán)引用的話,remove方法必定返回null
????????//?所以這個remove(cacheKey)?!=?bean肯定會成立
????????//?如果發(fā)生循環(huán)依賴的話,這個判斷就不會成立
????????//?這個我們在介紹循環(huán)依賴的時候再詳細分析,
????????//?目前你只需要知道wrapIfNecessary完成了AOP代理
????????if?(this.earlyProxyReferences.remove(cacheKey)?!=?bean)?{
????????????//?需要代理的話,在這里完成的代理
????????????return?wrapIfNecessary(bean,?beanName,?cacheKey);
????????}
????}
????return?bean;
}
4、wrapIfNecessary方法執(zhí)行
protected?Object?wrapIfNecessary(Object?bean,?String?beanName,?Object?cacheKey)?{
???
????//?在postProcessBeforeInstantiation方法中可能已經完成過代理了
????//?如果已經完成代理了,那么直接返回這個代理的對象
????if?(StringUtils.hasLength(beanName)?&&?this.targetSourcedBeans.contains(beanName))?{
????????return?bean;
????}
????
????//?在postProcessBeforeInstantiation方法中可能已經將其標記為不需要代理了
????//?這種情況下,也直接返回這個Bean
????if?(Boolean.FALSE.equals(this.advisedBeans.get(cacheKey)))?{
????????return?bean;
????}
????
????//?跟在postProcessBeforeInstantiation方法中的邏輯一樣
????//?如果不需要代理,直接返回,同時在advisedBeans中標記成false
????if?(isInfrastructureClass(bean.getClass())?||?shouldSkip(bean.getClass(),?beanName))?{
????????this.advisedBeans.put(cacheKey,?Boolean.FALSE);
????????return?bean;
????}
????//?獲取可以應用到這個Bean上的通知
????Object[]?specificInterceptors?=?getAdvicesAndAdvisorsForBean(bean.getClass(),?beanName,?null);
????//?如果存在通知的話,說明需要被代理
????if?(specificInterceptors?!=?DO_NOT_PROXY)?{
????????this.advisedBeans.put(cacheKey,?Boolean.TRUE);
????????//?到這里創(chuàng)建代理,實際上底層就是new了一個ProxyFactory來創(chuàng)建代理的
????????Object?proxy?=?createProxy(
????????????bean.getClass(),?beanName,?specificInterceptors,?new?SingletonTargetSource(bean));
????????this.proxyTypes.put(cacheKey,?proxy.getClass());
????????return?proxy;
????}
?//?如果沒有通知的話,也將這個Bean標記為不需要代理
????this.advisedBeans.put(cacheKey,?Boolean.FALSE);
????return?bean;
}
關于創(chuàng)建代理的具體源碼分析,在Spring中AOP相關的API及源碼解析,原來AOP是這樣子的一文中已經做了詳細介紹,所以本文不再贅述,現(xiàn)在我們的重點將放在Spring是如何解析出來通知的,對應方法就是getAdvicesAndAdvisorsForBean,其源碼如下:
第一步:調用org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
protected?Object[]?getAdvicesAndAdvisorsForBean(
??????Class>?beanClass,?String?beanName,?@Nullable?TargetSource?targetSource)?{
??
???//?通過findEligibleAdvisors方法返回對應的通知
???//?這個方法會返回所有能應用在指定的Bean上的通知
???List?advisors?=?findEligibleAdvisors(beanClass,?beanName);
???
???if?(advisors.isEmpty())?{
??????return?DO_NOT_PROXY;
???}
???return?advisors.toArray();
}
第二步:調用org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
protected?List?findEligibleAdvisors(Class>?beanClass,?String?beanName)? {
????//?獲取到所有的通知
????List?candidateAdvisors?=?findCandidateAdvisors();
????//?從獲取到的通知中篩選出能應用到這個Bean上的通知
????List?eligibleAdvisors?=?findAdvisorsThatCanApply(candidateAdvisors,?beanClass,?beanName);
????extendAdvisors(eligibleAdvisors);
????if?(!eligibleAdvisors.isEmpty())?{
????????eligibleAdvisors?=?sortAdvisors(eligibleAdvisors);
????}
????return?eligibleAdvisors;
}
第三步:調用org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors獲取到所有的通知
//?這個方法的目的就是為了獲取到所有的通知
protected?List?findCandidateAdvisors()? {
???
????//?先調用父類的方法,父類會去查找容器中所有屬于Advisor類型的Bean
????List?advisors?=?super.findCandidateAdvisors();
????
???//?這個類本身會通過一個aspectJAdvisorsBuilder來構建通知
????//?構建的邏輯就是解析@Aspect注解所標注的類中的方法
????if?(this.aspectJAdvisorsBuilder?!=?null)?{
????????advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
????}
????
????//?最后返回這些通知
????return?advisors;
}
第四步:org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors構建通知,這個方法比較長,我們就只分析其中的關鍵代碼即可
public?List?buildAspectJAdvisors()? {
??List?aspectNames?=?this.aspectBeanNames;
??if?(aspectNames?==?null)?{
???synchronized?(this)?{
????aspectNames?=?this.aspectBeanNames;
????if?(aspectNames?==?null)?{
?????List?advisors?=?new?ArrayList<>();
?????aspectNames?=?new?ArrayList<>();
?????//?會獲取到容器中的所有BeanName
?????String[]?beanNames?=?BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
???????this.beanFactory,?Object.class,?true,?false);
?????for?(String?beanName?:?beanNames)?{
??????//?如果對beanName配置了正則匹配的話,那么要按照正則表達式的匹配規(guī)則進行過濾
??????//?默認是沒有的,可以認為isEligibleBean始終返回true
??????if?(!isEligibleBean(beanName))?{
???????continue;
??????}
??????//?We?must?be?careful?not?to?instantiate?beans?eagerly?as?in?this?case?they
??????//?would?be?cached?by?the?Spring?container?but?would?not?have?been?weaved.
??????Class>?beanType?=?this.beanFactory.getType(beanName);
??????if?(beanType?==?null)?{
???????continue;
??????}
??????//?判斷類上是否添加了@Aspect注解
??????if?(this.advisorFactory.isAspect(beanType))?{
???????aspectNames.add(beanName);
???????AspectMetadata?amd?=?new?AspectMetadata(beanType,?beanName);
???????//?默認就是SINGLETON,代理切面對象是單例的
???????if?(amd.getAjType().getPerClause().getKind()?==?PerClauseKind.SINGLETON)?{
????????????????????????????//?最后從這個切面實例中解析出所有的通知
????????????????????????????//?關于通知解析的具體代碼就不再分析了
?????????MetadataAwareAspectInstanceFactory?factory?=
??????????new?BeanFactoryAspectInstanceFactory(this.beanFactory,?beanName);
????????List?classAdvisors?=?this.advisorFactory.getAdvisors(factory);
????????if?(this.beanFactory.isSingleton(beanName))?{
?????????this.advisorsCache.put(beanName,?classAdvisors);
????????}
????????else?{
?????????this.aspectFactoryCache.put(beanName,?factory);
????????}
????????advisors.addAll(classAdvisors);
???????}
??//?省略部分代碼
??return?advisors;
?}
第五步:org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
protected?List?findAdvisorsThatCanApply(
????List?candidateAdvisors,?Class>?beanClass,?String?beanName) ? {
????ProxyCreationContext.setCurrentProxiedBeanName(beanName);
????try?{
????????return?AopUtils.findAdvisorsThatCanApply(candidateAdvisors,?beanClass);
????}
????finally?{
????????ProxyCreationContext.setCurrentProxiedBeanName(null);
????}
}
這個方法其實沒啥好分析的,就是根據(jù)前面找出來的Advisor集合進行遍歷,然后根據(jù)每個Advisor對應的切點來進行匹配,如何合適就返回,對應源碼也比較簡單,當然前提是你看過我之前那篇AOP源碼分析的文章了.
總結
這篇文章比較短,因為沒有做很細節(jié)的源碼分析,比較詳細的源碼分析已經放到上篇文章中了。最后我這里畫個流程圖總結一下AOP是怎么被應用到Bean的生命周期中的

Spring源碼的最后一點補充
protected?Object?doCreateBean(String?beanName,?RootBeanDefinition?mbd,?@Nullable?Object[]?args)
????throws?BeanCreationException?{
????//?1.實例化????--->?createBeanInstance
????//?2.屬性注入??--->?populateBean
????//?3.初始化????--->?完成初始化及AOP
????//?exposedObject?就是完成初始化后的Bean??
????//?省略部分代碼,省略代碼的作用已經在上面標明了
????
????//?下面的代碼實際上主要目的在于處理循環(huán)依賴
????if?(earlySingletonExposure)?{
????????Object?earlySingletonReference?=?getSingleton(beanName,?false);
????????if?(earlySingletonReference?!=?null)?{
????????????if?(exposedObject?==?bean)?{
????????????????exposedObject?=?earlySingletonReference;
????????????}
????????????//?我們之前早期暴露出去的Bean跟現(xiàn)在最后要放到容器中的Bean不是同一個
????????????//?allowRawInjectionDespiteWrapping為false
????????????//?并且當前Bean被當成依賴注入到了別的Bean中
????????????else?if?(!this.allowRawInjectionDespiteWrapping?&&?hasDependentBean(beanName))?{
????????????????//?獲取到當前Bean所從屬的Bean
????????????????String[]?dependentBeans?=?getDependentBeans(beanName);
????????????????//?要得到真實的從屬的Bean
????????????????Set?actualDependentBeans?=?new?LinkedHashSet<>(dependentBeans.length);
????????????????for?(String?dependentBean?:?dependentBeans)?{
????????????????????//?移除那些僅僅為了類型檢查而創(chuàng)建出來
????????????????????if?(!removeSingletonIfCreatedForTypeCheckOnly(dependentBean))?{
????????????????????????actualDependentBeans.add(dependentBean);
????????????????????}
????????????????}
????????????????if?(!actualDependentBeans.isEmpty())?{
?????//?拋出異常
????????????????????//?出現(xiàn)了循環(huán)依賴,并且實際存在容器中的Bean跟被當作依賴注入到別的Bean中的
????????????????????//?不是同一個對象,這個時候也報錯
????????????????}
????????????}
????????}
????}
????//?注冊bean的銷毀回調
????try?{
????????registerDisposableBeanIfNecessary(beanName,?bean,?mbd);
????}
????catch?(BeanDefinitionValidationException?ex)?{
????????throw?new?BeanCreationException(
????????????mbd.getResourceDescription(),?beanName,?"Invalid?destruction?signature",?ex);
????}
????return?exposedObject;
}
實際這段代碼還是跟循環(huán)依賴相關,關于循環(huán)依賴的文章,大家可以參考:面試必殺技,講一講Spring中的循環(huán)依賴
如果我的文章能幫到你,記得點個贊哈~!
我叫DMZ,一個在學習路上匍匐前行的小菜鳥!
—?【 THE END 】— 本公眾號全部博文已整理成一個目錄,請在公眾號里回復「m」獲??! 3T技術資源大放送!包括但不限于:Java、C/C++,Linux,Python,大數(shù)據(jù),人工智能等等。在公眾號內回復「1024」,即可免費獲?。。?/span>
