一诅挑,@EnableAspectJAutoProxy開啟AspectJ自動(dòng)代理
在這個(gè)注解中導(dǎo)入了一個(gè)@Import(AspectJAutoProxyRegistrar.class)類。這個(gè)類實(shí)現(xiàn)了ImportBeanDefinitionRegistrar(Bean定義的注冊(cè)器)泛源,AspectJAutoProxyRegistrar實(shí)現(xiàn)了一個(gè)registerBeanDefinitions方法拔妥。通過AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);去獲取名為AUTO_PROXY_CREATOR_BEAN_NAME="org.springframework.aop.config.internalAutoProxyCreator"的Bean定義信息;然后幫我們導(dǎo)入AnnotationAwareAspectJAutoProxyCreator這個(gè)組件
二,AnnotationAwareAspectJAutoProxyCreator展開調(diào)查
1达箍,如圖可知没龙,AnnotationAwareAspectJAutoProxyCreator這個(gè)類同時(shí)具有BeanFactory和BeanPostProcessor屬性。點(diǎn)進(jìn)去這個(gè)類,看看他們是怎么實(shí)現(xiàn)的硬纤,點(diǎn)進(jìn)去發(fā)現(xiàn)AnnotationAwareAspectJAutoProxyCreator這個(gè)類本身并沒有什么我們想要的解滓,但是他有父類。一直點(diǎn)筝家,找到最后一層父類AbstractAutoProxyCreator洼裤。
2通過查看,最終找到如下關(guān)系溪王,由于AnnotationAwareAspectJAutoProxyCreator是AbstractAutoProxyCreator的子類腮鞍,所以就找到AnnotationAwareAspectJAutoProxyCreator和BeanPostProcessor的關(guān)系,實(shí)現(xiàn)了一個(gè)后置處理器的前置方法莹菱。然后再找AnnotationAwareAspectJAutoProxyCreator和BeanFactroyAware的關(guān)系移国。AbstractAutoProxyCreator實(shí)現(xiàn)了postProcessBeforeInstantiation接口而postProcessBeforeInitialization是開放式接口。用于開發(fā)者自己實(shí)現(xiàn)
3道伟,通過下面圖可知迹缀,找到他們之間的關(guān)系
4,下面給出一張完整的關(guān)系圖蜜徽。
5祝懂,接下來就圍繞這張關(guān)系圖去找主要的類,找主要的方法去理清楚AOP的實(shí)現(xiàn)過程拘鞋。由上圖可知嫂易,一個(gè)最主要的類就是AbstractAutoProxyCreator,還有最主要的兩個(gè)方法也就是那個(gè)后置處理器的前置方法和后置方法掐禁。postProcessBeforeInstantiation、postProcessAfterInitialization颅和、下面一個(gè)一個(gè)進(jìn)行分析傅事。
三,postProcessBeforeInstantiation
一峡扩,找事務(wù)的增強(qiáng)器蹭越。
還記得之前的IOC的那篇文章在執(zhí)行doCreateBean之前,resolveBeforeInstantiation這個(gè)方法將Bean定義信息進(jìn)行了代理教届。并且放入了緩存中响鹃。postProcessBeforeInstantiation這個(gè)方法就是從resolveBeforeInstantiation這里方法里面走進(jìn)來的。點(diǎn)進(jìn)postProcessBeforeInstantiation這個(gè)方法案训,Object cacheKey = getCacheKey(beanClass, beanName);進(jìn)來就去從緩存拿买置,然后看isInfrastructureClass這個(gè)方法,判斷的是是不是基礎(chǔ)的Bean强霎。什么是基礎(chǔ)Bean比如Advice.class\Pointcut.class\Advisor.class等等等忿项。然后還要判斷shouldSkip()這個(gè)方法應(yīng)不應(yīng)該跳過。點(diǎn)進(jìn)去我們發(fā)現(xiàn)有一個(gè)這樣的findCandidateAdvisors()方法,這個(gè)方法就是在找事務(wù)的增強(qiáng)器轩触。那么為什么這么說寞酿,因?yàn)樵诟割惱锿ㄟ^advisorRetrievalHelper(切面查找工具類)這個(gè)類的findAdvisorBeans方法可知并沒有找到實(shí)現(xiàn)了Advisor.class的類。從上圖也能看出AnnotationAwareAspectJAutoProxyCreator的類圖里面也沒有看到跟Advisor.class相關(guān)的類或者實(shí)現(xiàn)脱柱。這個(gè)方法是怎么判斷的呢?它進(jìn)來先是從緩存里面去拿伐弹,沒拿到,緊接著去容器當(dāng)中去找榨为。BeanFactoryUtils.beanNamesForTypeIncludingAncestors惨好,也沒找到,所以直接返回了一個(gè)空的List對(duì)象柠逞。由此可知昧狮,我們可以把findCandidateAdvisors()方法理解為在查找事務(wù)的增強(qiáng)器。下面給出一張流程圖便于理解板壮。
二逗鸣,尋找我們自己定義的AspectJ
findCandidateAdvisors()這個(gè)方法走完以后,沒找到關(guān)于事務(wù)的切面绰精,然后接著往下走this.aspectJAdvisorsBuilder.buildAspectJAdvisors()這段代碼點(diǎn)進(jìn)去撒璧,進(jìn)去發(fā)現(xiàn)第一次this.aspectBeanNames獲取依然是null,然后如果為空的話笨使,通過BeanFactoryUtils.beanNamesForTypeIncludingAncestors這個(gè)東西卿樱,把所有的類的名稱都撈出來。然后通過for循環(huán)你的BeanName去獲取你的BeanType硫椰,然后判斷你的beanType是不是AspectJ繁调。如果 是接著往下走找到getAdvisors方法。第一步獲取增強(qiáng)器的類型getAspectMetadata().getAspectClass()靶草。 在獲取增強(qiáng)器的名稱蹄胰。再往下看,有一個(gè)for循環(huán)奕翔,里面有一個(gè)getAdvisorMethods方法裕寨,也就是去循環(huán)你的這個(gè)方法,點(diǎn)到這個(gè)方法里面看一看派继,然后會(huì)發(fā)現(xiàn)宾袜,通過這個(gè)doWithMethods方法,會(huì)把你所有的增強(qiáng)器撈出來驾窟。并且要排除你的切點(diǎn)(Pointcut.class)庆猫。
三, 獲取增強(qiáng)器getAdvisors
1首先循環(huán)你所有去除切點(diǎn)的增強(qiáng)器方法。沒循環(huán)一次調(diào)用一次getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName)方法绅络。點(diǎn)進(jìn)getAdvisor方法阅悍。接下來找到一個(gè)創(chuàng)建切面的實(shí)現(xiàn)類InstantiationModelAwarePointcutAdvisorImpl(實(shí)例化切面)好渠,點(diǎn)進(jìn)去,這個(gè)方法里前面做了一些基礎(chǔ)賦值和判斷是否是懶加載等校驗(yàn)节视。下面有個(gè)最關(guān)鍵的方法instantiateAdvice(this.declaredPointcut);點(diǎn)進(jìn)去找到getAdvice方法(獲取通知)拳锚。在這個(gè)方法中找到AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod)這個(gè)方法,他是意思是說寻行,在方法上找到所有的切面上的注解霍掺。這個(gè)方法里會(huì)遍歷如下圖所示的類。如果找到了直接返回到getAdvice這個(gè)方法拌蜘。
2杆烁,回到getAdvice方法中可以看到下面有一個(gè)switch選擇。如下圖简卧,通過這switch判斷你或取到的注解的類型是什么東東兔魂。如果是before就new一個(gè)AspectJMethodBeforeAdvice,這個(gè)東西就是切面通知举娩。到這里直接就返回到getAdvisors方法中把它放入advisors中去析校。下面在畫一張流程圖
3,流程圖
3铜涉,最終執(zhí)行完智玻,在buildAspectJAdvisors()方法中把剛才找到的切面都放入切面的緩存中去this.advisorsCache.put(beanName, classAdvisors)和this.aspectFactoryCache.put(beanName, factory);放到這兩個(gè)緩存里面來。至此shouldSkip()方法執(zhí)行完畢芙代。最后發(fā)現(xiàn)?postProcessBeforeInstantiation這個(gè)東西他就是說將我們自己定義切面都給撈出來吊奢。并且放入增強(qiáng)器緩存中。
四:postProcessAfterInitialization創(chuàng)建代理對(duì)象纹烹。
點(diǎn)進(jìn)去這個(gè)方法页滚,也許有人會(huì)問這個(gè)方法是從哪里進(jìn)來的。在分析IOC的時(shí)候铺呵,說到了創(chuàng)建屬性的那個(gè)方法逻谦,在后面進(jìn)行初始化的時(shí)候,執(zhí)行了一些后置處理器postProcessAfterInitialization 這個(gè)方法就是從invokeInitMethods方法中的applyBeanPostProcessorsAfterInitialization方法進(jìn)來的陪蜻。
點(diǎn)進(jìn)去wrapIfNecessary這個(gè)方法前面執(zhí)行了一些判斷找到getAdvicesAndAdvisorsForBean這個(gè)方法。找Advices類型的和Advisors這個(gè)類型贱鼻,這個(gè)方法是找事務(wù)和AOP都是通過這個(gè)方法宴卖。因?yàn)槭聞?wù)和AOP的執(zhí)行流程很相似,事務(wù)的流程在后面的文章會(huì)進(jìn)行講解邻悬。那么這個(gè)方法到底做了什么呢症昏。看名知意父丰。點(diǎn)進(jìn)去發(fā)現(xiàn)了findEligibleAdvisors這個(gè)方法肝谭,找到一個(gè)合適的增強(qiáng)器掘宪。再點(diǎn)進(jìn)去∪林颍看第一行findCandidateAdvisors()又執(zhí)行了一次魏滚,所以里面流程不會(huì)走,而是直接從緩存中拿到了增強(qiáng)器坟漱。因?yàn)樵赽efore中我們創(chuàng)建過了鼠次。既然找到了那么應(yīng)該怎么辦呢,看下面的方法
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
這個(gè)意思就是說找到我本類能用的芋齿。比如說你現(xiàn)在有兩個(gè)切面腥寇,當(dāng)本類是A的時(shí)候,那么只能有其中的一個(gè)切面對(duì)我進(jìn)行增強(qiáng)的植入觅捆,那么另一個(gè)可能在切另外一個(gè)類赦役,所以這個(gè)方法就是找出我奔雷能用的切面。點(diǎn)進(jìn)去看看栅炒。然后找到方法canApply(candidate, clazz, hasIntroductions)掂摔,意思是能用的。順便強(qiáng)調(diào)一下职辅,我們只看有用的代碼邊邊角角這里不做介紹棒呛。點(diǎn)進(jìn)canApply方法。在其中你會(huì)發(fā)現(xiàn)有一段advisor? ?instanceof PointcutAdvisor域携,PointcutAdvisor pca = (PointcutAdvisor) advisor;將獲取到的進(jìn)行轉(zhuǎn)換一下看看是否能用簇秒。在點(diǎn)進(jìn)去canApply,這里面是一個(gè)方法的匹配器秀鞭。通過循環(huán)去匹配看看我們能不能用趋观。最后執(zhí)行完,直接返回到getAdvicesAndAdvisorsForBean這個(gè)方法中锋边,這個(gè)方法會(huì)判斷皱坛,如果找到空的就不需要代理。如果找到了下一步就通過wrapIfNecessary這個(gè)方法中的createProxy來進(jìn)行代理豆巨。
2剩辟,createProxy
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);暴露代理對(duì)象
意思就是:@EnableAspectJAutoProxy(exposeProxy =true)暴露代理對(duì)象
點(diǎn)進(jìn)createProxy方法,找到buildAdvisors方法點(diǎn)進(jìn)去,把返回的切面數(shù)組放入proxyFactory.最后找到getProxy這個(gè)方法點(diǎn)進(jìn)去,其實(shí)這個(gè)方法就是真正的去代理的對(duì)象.找到createAopProxy這個(gè)方法.其中一段targetClass.isInterface() || Proxy.isProxyClass(targetClass)如果是接口,或者Proxy的類就用jdk去代理,否則用Cglib去代理或者強(qiáng)制指定Cglib去代理,否則就用jdk去代理.執(zhí)行完返回來,找到getProxy方法,Proxy.newProxyInstance(classLoader, proxiedInterfaces,this);真正的去創(chuàng)建代理對(duì)象.
五,總結(jié)
創(chuàng)建AOP的代理對(duì)象主要就是如下幾點(diǎn)流程,第一postProcessBeforeInstantiation這個(gè)后置處理器就是找到你所有的切面信息.并且放入緩存中去,postProcessAfterInitialization這個(gè)后置處理器就是創(chuàng)建我們的代理對(duì)象.其中的一些校驗(yàn),細(xì)節(jié),上面也有部分的講解.AOP(創(chuàng)建代理對(duì)象)至此結(jié)束,下面附上一張整體的流程圖.