<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 12905字,需瀏覽 26分鐘

           ·

          2020-07-28 12:36

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


          所以本文我們接著來看看initializeBean這個方法,它主要干了這么幾件事

          1. 執(zhí)行Aware接口中的方法
          2. 執(zhí)行生命周期回調方法
          3. 完成AOP代理

          對應源碼如下:

          protected?Object?initializeBean(String?beanName,?Object?bean,?@Nullable?RootBeanDefinition?mbd)?{
          ??if?(System.getSecurityManager()?!=?null)?{
          ???AccessController.doPrivileged((PrivilegedAction)?()?->?{
          ????invokeAwareMethods(beanName,?bean);
          ????return?null;
          ???},?getAccessControlContext());
          ??}
          ??else?{
          ???????????
          ????????????//?執(zhí)行Aware接口中的方法
          ???invokeAwareMethods(beanName,?bean);
          ??}

          ??Object?wrappedBean?=?bean;
          ??if?(mbd?==?null?||?!mbd.isSynthetic())?{
          ????????????
          ????????????//?調用InitDestroyAnnotationBeanPostProcessor
          ????????????//?的postProcessBeforeInitialization方法
          ????????????//?處理@PostContructor注解標注的方法
          ????????????//?另外有一部分aware方法也是在這里調用的
          ???wrappedBean?=?applyBeanPostProcessorsBeforeInitialization(wrappedBean,?beanName);
          ??}

          ??try?{
          ????????????//?如果實現(xiàn)了InitializingBean,會調用afterPropertiesSet方法
          ????????????//?如果XML中配置了init-method屬性,會調用對應的初始化方法
          ???invokeInitMethods(beanName,?wrappedBean,?mbd);
          ??}
          ??catch?(Throwable?ex)?{
          ???throw?new?BeanCreationException(
          ?????(mbd?!=?null???mbd.getResourceDescription()?:?null),
          ?????beanName,?"Invocation?of?init?method?failed",?ex);
          ??}
          ??if?(mbd?==?null?||?!mbd.isSynthetic())?{
          ????????????//?在這里完成AOP
          ???wrappedBean?=?applyBeanPostProcessorsAfterInitialization(wrappedBean,?beanName);
          ??}

          ??return?wrappedBean;
          ?}

          因為在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注解向容器中注冊一個AnnotationAwareAspectJAutoProxyCreatorBeanDefinition,它本身也是一個BeanPostProcessor,這個BeanDefinition會在org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors這個方法中完成創(chuàng)建,如下圖所示


          2、postProcessBeforeInstantiation方法執(zhí)行

          執(zhí)行AnnotationAwareAspectJAutoProxyCreatorpostProcessBeforeInstantiation方法,實際上就是父類AbstractAutoProxyCreatorpostProcessBeforeInstantiation被執(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>




          瀏覽 78
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    亚洲中文无码视 | 亚洲色欧美另类 | 无码在线直播 | 夜夜操夜夜爱 | 中学生妹一级特黄毛片 |