所有文章已遷移至csdn,csdn個(gè)人主頁(yè)bugpool.blog.csdn.net
本篇旨在讓讀者對(duì)Spring AOP實(shí)現(xiàn)原理有一個(gè)宏觀上的認(rèn)識(shí),因此會(huì)丟失一些細(xì)節(jié)咕幻,具體實(shí)現(xiàn)參考:老實(shí)人Spring源碼目錄
閱讀本篇文章前,希望讀者對(duì)Spring Ioc以及Spring AOP的使用(@Aspect)由一定了解,話不多說(shuō)流椒,直接上圖
準(zhǔn)備工作
-
Service
類:有find方法跟save方法,find方法前后需要緩存操作明也,save方法前后需要事務(wù)操作 -
CacheableAspect
切面類:用于在Service的find方法前后進(jìn)行緩存操作 -
TransctionlAspect
切面類:用于在Service的save方法進(jìn)行事務(wù)操作 -
LogAspect
切面類:記錄所有Controller的請(qǐng)求日志
AOP準(zhǔn)備
Spring AOP自動(dòng)代理時(shí)機(jī)
在service
bean的創(chuàng)建過(guò)程中(也就是getBean("service")
)宣虾,AOP通過(guò)BeanPostProcess后置處理器操作進(jìn)行介入
分為2種情況:
- 用戶自定義了
targetSource
,則bean的創(chuàng)建(實(shí)例化温数、填充安岂、初始化)均由用戶負(fù)責(zé),Spring Ioc不會(huì)在管該代理目標(biāo)對(duì)象traget
帆吻,這種情況基本上不會(huì)發(fā)生域那,很多人用了幾年Spring可能都不知道有它的存在 - 正常情況下都是Spring Ioc完成代理對(duì)象
target
的實(shí)例化、填充猜煮、初始化次员。然后在初始化后置處理器中進(jìn)行介入,對(duì)bean
也就是service
進(jìn)行代理
Spring AOP代理時(shí)機(jī)
創(chuàng)建代理操作wrapIfNecessary
所有的重點(diǎn)都在wrapIfNecessary
做了什么操作
代理的方法調(diào)用
創(chuàng)建完代理王带,代理如果調(diào)用方法呢淑蔚?我們以Jdk動(dòng)態(tài)代理
為例子,方法的調(diào)用將會(huì)觸發(fā)invoke
方法愕撰。具體源碼參考Jdk動(dòng)態(tài)代理 底層源碼
Spring AOP攔截器的執(zhí)行順序
從上面可以看出刹衫,Spring AOP的代理invoke
方法,其實(shí)是攔截器
的執(zhí)行搞挣。
我們先了解一下Spring AOP的執(zhí)行順序带迟,跟棧
很像,后進(jìn)先出
AOP攔截器執(zhí)行原理
那么這個(gè)攔截器鏈又如何保證before
在after
之前呢囱桨?而且還能保證find
方法的執(zhí)行順序仓犬?詳情參考MethodInvocation攔截器調(diào)用原理
這部分實(shí)現(xiàn)原理通過(guò)幾句話是解釋不完的,只能給出圖大家了解個(gè)大概
具體攔截器源碼:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 先調(diào)用before方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 繼續(xù)鏈?zhǔn)秸{(diào)用
return mi.proceed();
}
}
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 先進(jìn)行鏈?zhǔn)秸{(diào)用
Object retVal = mi.proceed();
// 再調(diào)用afterReturning方法
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
}
壓軸題:Spring AOP遇上循環(huán)依賴
該部分難度系數(shù)十顆星舍肠,算是Spring源碼最復(fù)雜的一塊搀继,這塊弄懂可以說(shuō)對(duì)Spring的理解已經(jīng)達(dá)到阿里水準(zhǔn)了窘面。這里三言兩語(yǔ)是不可能解釋清楚的,只能貼個(gè)圖叽躯,大家有個(gè)宏觀上的認(rèn)知财边,詳情Spring AOP遇上循環(huán)依賴
總結(jié)
Spring AOP是Spring重要的組成部分之一,本篇只是給讀者宏觀上的一個(gè)認(rèn)識(shí)点骑,具體還是需要閱讀源碼酣难。
畫圖不容易啊,麻煩各位大佬給個(gè)贊畔况!有不懂的問(wèn)題可以留言鲸鹦,會(huì)一一解答,有寫錯(cuò)的地方也歡迎探討跷跪!