Spring AOP底層源碼詳解
ProxyFactory的工作原理
ProxyFactory是一個代理對象生產(chǎn)工廠,在生成代理對象之前需要對代理工廠進行配置。ProxyFactory在生成代理對象之前需要決定到底是使用JDK動態(tài)代理還是CGLIB技術(shù)。
// config就是ProxyFactory對象
// optimize為true,或proxyTargetClass為true,或用戶沒有給ProxyFactory對象添加interface
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// targetClass是接口,直接使用Jdk動態(tài)代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 使用Cglib
return new ObjenesisCglibAopProxy(config);
}
else {
// 使用Jdk動態(tài)代理
return new JdkDynamicAopProxy(config);
}
JdkDynamicAopProxy創(chuàng)建代理對象過程
- 獲取生成代理對象所需要實現(xiàn)的接口集合
- 獲取通過ProxyFactory.addInterface()所添加的接口,如果沒有通過ProxyFactory.addInterface()添加接口,那么則看ProxyFactory。setTargetClass()所設(shè)置的targetClass是不是一個接口,把接口添加到結(jié)果集合中,同時把SpringProxy、Advised、DecoratingProxy這幾個接口也添加到結(jié)果集合中去。
- 確定好要代理的集合之后,就利用Proxy.newProxyInstance()生成一個代理對象。
JdkDynamicAopProxy創(chuàng)建代理對象執(zhí)行過程
- 如果通過ProxyFactory.setExposeProxy()把exposeProxy設(shè)置為true,那么則把代理對象設(shè)置到一個ThreadLocal(currentProxy)中去。
- 獲取通過ProxyFactory所設(shè)置的target,如果設(shè)置的是targetClass,那么target將為null
- 根據(jù)當(dāng)前所調(diào)用的方法對象尋找ProxyFactory中所添加的并匹配的Advisor,并且把Advisor封裝為MethodInterceptor返回,得到MethodIntercepter鏈叫做chain
- 如果chain為空,則字節(jié)執(zhí)行target對應(yīng)的當(dāng)前方法,如果target為null會報錯
- 如果chain不為空,則會依次執(zhí)行chain中的MethodInterceptor。如果當(dāng)前MethodInterceptor是MethodBeforeAdviceInterceptor,那么先執(zhí)行Advisor中所advice的before()方法,然后執(zhí)行下一個MethodInterceptor.如果當(dāng)前MethodInterceptor是AfterReturningAdviceInterceptor,那么先執(zhí)行執(zhí)行下一個MethodInterceptor。拿到返回值后,再執(zhí)行Advisor中所advice的afterReturning()方法
ObjenesisCglibAopProxy創(chuàng)建代理對象過程
- 創(chuàng)建Enhancer
- 設(shè)置Enhancer的superClass為通過ProxyFactory.setTarget()所設(shè)置的對象的類
- 設(shè)置Enhancer的interfaces為通過ProxyFactory.addInterface()所添加的接口,以及SpringProxy、Advisor接口
- 設(shè)置Enhancer的Callbacks為DynamicAdvisedIntercepter
- 最后通過Enhancer創(chuàng)建一個代理對象
ObjenesisCglibAopProxy創(chuàng)建的代理對象執(zhí)行過程
執(zhí)行過程主要就看DynamicAdvisedInterceptor中的實現(xiàn),執(zhí)行邏輯和JdkDynamicAopProxy中是一樣的。
自動代理(autoproxy)功能
“自動代理”表示只需要在Spring中添加某個Bean,這個Bean是一個BeanPostProcessor,那么Spring在每創(chuàng)建一個Bean時,都會經(jīng)過這個BeanPost Processor的判斷,去判斷當(dāng)前正在創(chuàng)建的這個Bean是不是需要進行AOP。
DefaultAdvisorAutoProxyCreator
AbstractAutoProxyCreator實現(xiàn)了SmartInstantiationAwareBeanPostProcessor接口,是一個BeanPostProcessor
- 在某個Bean實例化之前,查看該AbstractAutoProxyCreator中是不是設(shè)置了CustomTargetSource,如果設(shè)置了就查看當(dāng)前Bean是不是需要創(chuàng)建一個TargetSource,如果需要就會創(chuàng)建一個TargetSource對象,然后進行AOP創(chuàng)建一個代理對象,并返回該代理對象
- 如果某個Bean出現(xiàn)了循環(huán)依賴,那么會利用getEarlyBeanReference()方法提前進行AOP
- 在某個Bean初始化之后,會調(diào)用wrapIfNecessary()方法進行AOP
- 在這個類中提供了一個抽象方法:getAdvicesAndAdvisorsForBean(),表示對于某個Bean匹配了哪些Advices和Advisors
AbstractAdvisorAutoProxyCreator繼承了AbstractAutoProxyCreator,AbstractAdvisorAutoProxyCreator中實現(xiàn)了getAdvicesAndAdvisorsForBean()方法,實現(xiàn)邏輯為:
- 調(diào)用findEligibleAdvisors()
- 調(diào)用findCandidateAdvisors,得到所有Advisor類型的Bean。按當(dāng)前正在進行Bean的生命周期的Bean進行過濾
@EnableAspectJAutoProxy
這個注解主要是添加了一個AnnotationAwareAspectJAutoProxyCreator類型的BeanDefinition。AspectJAwareAdvisorAutoProxyCreator繼承了AbstractAdvisorAutoProxyCreator,重寫了shouldSkip(Class<?> beanClass, String beanName)方法,表示某個bean需不需要進行AOP,在shouldSkip()方法中:
- 拿到所有的Advisor
- 遍歷所有的Advisor,如果當(dāng)前bean是AspectJPointcutAdvisor,那么則跳過
AnnotationAwareAspectJAutoProxyCreator繼承了AspectJAwareAdvisorAutoProxyCreator,重寫了findCandidateAdvisors()方法,它即可以找到Advisor類型的bean,也能把所有@Aspect注解標(biāo)注的類掃描出來并生成Advisor
注解和源碼對應(yīng)關(guān)系
@Before對應(yīng)的是AspectJMethodBeforeAdvice,直接實現(xiàn)MethodBeforeAdvice,在進行動態(tài)代理時會把AspectJMethodBeforeAdvice轉(zhuǎn)成MethodBeforeAdviceInterceptor,也就轉(zhuǎn)變成了MethodBeforeAdviceInterceptor
- 先執(zhí)行advice對應(yīng)的方法
- 再執(zhí)行MethodInvocation的proceed(),會執(zhí)行下一個Interceptor,如果沒有下一個Interceptor了,會執(zhí)行target對應(yīng)的方法
@After對應(yīng)的是AspectJAfterAdvice,直接實現(xiàn)了MethodInterceptor
- 先執(zhí)行MethodInvocation的proceed(),會執(zhí)行下一個Interceptor,如果沒有下一個Interceptor了,會執(zhí)行target對應(yīng)的方法
- 再執(zhí)行advice對應(yīng)的方法
@Around對應(yīng)的是AspectJAroundAdvice,直接實現(xiàn)了MethodInterceptor
直接執(zhí)行advice對應(yīng)的方法
@AfterThrowing對應(yīng)的是AspectJAfterThrowingAdvice,直接實現(xiàn)了MethodInterceptor
- 先執(zhí)行MethodInvocation的proceed(),會執(zhí)行下一個Interceptor,如果沒有下一個Interceptor了,會執(zhí)行target對應(yīng)的方法
- 如果上面拋了Throwable,那么則會執(zhí)行advice對應(yīng)的方法
@AfterReturning對應(yīng)的是AspectJAfterReturningAdvice,實現(xiàn)了AfterReturningAdvice,在進行動態(tài)代理時會把AspectJAfterReturningAdvice轉(zhuǎn)成AfterReturningAdviceInterceptor,也就轉(zhuǎn)變成了MethodInterceptor
- 先執(zhí)行MethodInvocation的proceed(),會執(zhí)行下一個Interceptor,如果沒有下一個Interceptor了,會執(zhí)行target對應(yīng)的方法
- 執(zhí)行上面的方法后得到最終的方法的返回值
- 再執(zhí)行Advice對應(yīng)的方法
以上就是Spring AOP底層源碼詳解的詳細內(nèi)容,更多關(guān)于Spring AOP底層源碼的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java后臺實現(xiàn)js關(guān)閉本頁面,父頁面指定跳轉(zhuǎn)或刷新操作
這篇文章主要介紹了java后臺實現(xiàn)js關(guān)閉本頁面,父頁面指定跳轉(zhuǎn)或刷新操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11
詳解springboot使用異步注解@Async獲取執(zhí)行結(jié)果的坑
本文主要介紹了springboot使用異步注解@Async獲取執(zhí)行結(jié)果的坑,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08
java實現(xiàn)HmacSHA256算法進行加密方式
這篇文章主要介紹了java實現(xiàn)HmacSHA256算法進行加密方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08
java 將字符串、list 寫入到文件,并讀取內(nèi)容的案例
這篇文章主要介紹了java 將字符串、list 寫入到文件,并讀取內(nèi)容的案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
關(guān)于Java應(yīng)用日志與Jaeger的trace關(guān)聯(lián)的問題
這篇文章主要介紹了Java應(yīng)用日志如何與Jaeger的trace關(guān)聯(lián),通過jaeger發(fā)現(xiàn)這十次請求中有一次耗時特別長,想定位一下具體原因,感興趣的朋友跟隨小編一起看看吧2022-01-01
Java Stream的基本概念以及創(chuàng)建方法
這篇文章主要介紹了Java Stream的基本概念以及創(chuàng)建方法,幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下2020-08-08

