分析貼
https://blog.csdn.net/jy02268879/article/details/88409710
https://www.cnblogs.com/nullllun/p/9222627.html
概述
在Bean初始化階段,Spring爲Bean生成代理對象,一個bean對象對應一個代理對象,代理對象的advisors:List中保存所有掃描到的和bean.class相關的AOP通知方法(Advisor)信息。每個通知方法中各自保存自己與bean.class中所有方法匹配的結果(yes\no)。給被代理方法生成調用鏈時,遍歷當前代理對象中advisors:List,通過各個AOP通知方法匹配結果,決定某個AOP通知方法是否加入調用鏈。
匹配流程:aopProxy(bean) -> dynamicAdvisedIntercepto -> advised -> 遍歷通知方法advisors[i] -> 切點pointcut.shadowMatchCache -> shadowMatchImpl.match(yes/no)
創建代理對象
通知方法排序
spring aop會在AnnotationAwareAspectJAutoProxyCreator處理bean查找到適配的Advisor的時候對所有Advisor進行排序並生成動態代理,AspectJAwareAdvisorAutoProxyCreator的sortAdvisors方法
@Override
@SuppressWarnings("unchecked")
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors =
new ArrayList<PartiallyComparableAdvisorHolder>(advisors.size());
//遍歷advisors 放入partiallyComparableAdvisors
for (Advisor element : advisors) {
partiallyComparableAdvisors.add(
new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR)); //默認比較器
}
//排序partiallyComparableAdvisors
List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
if (sorted != null) {
List<Advisor> result = new ArrayList<Advisor>(advisors.size());
//遍歷排序後partiallyComparableAdvisors,取出Advisor存入result
for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
result.add(pcAdvisor.getAdvisor());
}
return result;
}
else {
//直接排序advisors
return super.sortAdvisors(advisors);
}
}
這裏會根據每個Advisor的獲取到的order值進行從小到大排序,order值獲取規則如下:
- 首先判斷當前Advisor所在的切面類是否實現org.springframework.core.Ordered接口,是的話調用getOrder方法獲取
- 否則判斷當前Advisor所在的切面類是否包含org.springframework.core.annotation.Order註解,是的話從註解獲取
- 沒有取到值,默認爲最低優先級,值爲最大Int
從排序代碼可知,有以下處理過程:
- 打在Advice方法上的org.springframework.core.annotation.Order註解不予識別
- 如果一個切面類存在多個Advisor,則會按Advice方法的聲明順序,聲明在前的優先級高,先執行
- 不同切面類但是order值是一樣的,則按spring獲取到切面bean的順序做排序,先獲取先執行
調用過程
代理類結構
CGLIB代理對象:與Bean對象一對一。代理對象中保存了與被代理Bean相關的攔截器、派發器
aopProxy.dynamicAdvisedInterceptor.advisors:
ArrayList中保存所有和當前被代理Bean.class相關的AOP通知方法(Advisor)信息,自定義AOP方法被Spring封裝類型爲InstantiationModelAwarePointcutAdvisor類型對象。默認order=int.max。點開事務通知方法其order=2147483647(int.max)。
aopProxy.dynamicAdvisedInterceptor.advisors[2]:
自定義AOP通知方法被Spring封裝爲InstantiationModelAwarePointcutAdvisor類型對象。下圖是自定義通知方法的屬性。
advisors[2].pointcut:自定義AOP通知方法的切點信息
其中shadowMatchCache:Map中保存着當前通知方法配置切點與被代理Bean.class中各個方法的匹配結果。匹配結果是創建AOP通知鏈的依據。其key=Bean.class中各個方法對象
調用核心流程
通過AOP包裝的SpringBean對象調用方法時,首先執行其代理對象的動態通知攔截器的攔截方法
CglibAopProxy.DynamicAdvisedInterceptor#intercept
1、取得AOP通知方法攔截器鏈
//通過DynamicAdvisedInterceptor.advised取得當前被代理方法tagetMethod的通知方法攔截器鏈
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//緩存中匹配tagetMethod攔截器鏈
->List<Object> cached = this.methodCache.get(cacheKey);
//沒有命中緩存
->if (cached == null)
//生成攔截器鏈cached
->cached =this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
//遍歷代理對象中保存的類相關通知方法信息
->for (advisor:advisors)
//通知方法切點表達式 與 目標方法匹配 ?
-> if (advisor.pointcut.shadowMatchCache.get(tagetMethod).match==YES )
->cached.add(advisor)
//攔截器鏈存入緩存
->this.methodCache.put(cacheKey, cached);
->return cached;
2、若攔截器鏈chain爲空,直接method/methodProxy.invoke反射執行目標方法return。
3、攔截器鏈chain不爲空,實例化一個MethodInvocation mi(每次調用都新實例化mi),遞歸其proceed()。mi中包含一個index(執行標記)、執行鏈chain.....等。
chain:ArrayList 保存順序: Expose攔截器(0)->事務攔截器(1)->after攔截器(2)->around攔截器(3)->before攔截器(4),遞歸調用mi.proceed()。
數組+index+遞歸 實現鏈式調用
(2)after攔截器invoke:先遞進mi.proceed() -> chain[++index].invoke(),finally等待迴歸出棧時執行
(3)around攔截器invoke:反射執行@Around切面方法,切面方法中調用joinPoint.proceed(),繼續遞歸mi.proceed -> chain[++index].invoke()
(4)before攔截器invoke: 由(3)遞歸進入mi.proceed(),若chain中還有攔截器(before),執行before切面方法 -> 遞歸mi.proceed() -> chain[++index].invoke()。
(5)最終mi.proceed()執行到chain末尾,index==chain.size,開始執行目標方法,return方法出棧。
所以SpringAOP的執行順序:around前->before->目標方法->around後->after
//每次調用都實例化一個方法調用器MethodInvocation,遞歸調用proceed
new CglibMethodInvocation(....).proceed();
//ReflectiveMethodInvocation#proceed
public Object proceed() throws Throwable {
//this.currentInterceptorIndex =當前index 初始=-1
//this.interceptorsAndDynamicMethodMatchers=上邊產生的攔截器鏈chain
//判斷攔截器鏈是否調用完
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//執行目標方法,終止遞歸,方法出棧
return invokeJoinpoint();
}
//取出當前index+1的攔截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//攔截器類型檢測爲動態匹配
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
//匹配失敗,跳過當前攔截器,遞歸攔截器鏈下一個
return proceed();
}
}
else {
//攔截器類型檢測爲靜態匹配
//執行攔截器,將this傳入,invoke中遞歸當前方法this.proceed()
//此invoke根據MethodInterceptor類型不同,執行也不同
//Expose、@Around、@Before、@After......見下面各個invoke()
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
//ExposeInvocationInterceptor#invoke
//Expose類型攔截器
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
//參數mi就是上面的this
MethodInvocation oldInvocation = invocation.get();
//ThreadLocal<MethodInvocation> invocation
//線程暫存mi
invocation.set(mi);
try {
//遞歸上邊的proceed方法,到攔截器鏈下一個
return mi.proceed();
}
finally {
//重置invocation
invocation.set(oldInvocation);
}
}
//AspectJAfterAdvice#invoke
//@After攔截器
public Object invoke(MethodInvocation mi) throws Throwable {
try {
//遞歸下一個攔截器
return mi.proceed();
}
finally {
//proceed()終止遞歸,出棧到此時執行finally
//因爲是finally,無論有無異常,@After必執行的
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
//AspectJAroundAdvice#invoke
//@Around攔截器+執行目標方法+終止遞歸+出棧
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
//將mi轉爲ProxyMethodInvocation
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
//取得JoinPoint
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
//取得匹配器
JoinPointMatch jpm = getJoinPointMatch(pmi);
//執行-->invokeAdviceMethodWithGivenArgs
return invokeAdviceMethod(pjp, jpm, null, null);
}
//AbstractAspectJAdvice#invokeAdviceMethodWithGivenArgs
//@Around攔截器上面invokeAdviceMethod最終執行到此方法
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// aspectJAdviceMethod爲@Around註解的Method
// Method反射執行@Around切面方法
// 在切面中方法中調用joinPoint.proceed()
// 繼續遞歸proceed執行before方法+目標方法
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
//到此@Around切面方法+before方法+目標方法都已執行完成,return出棧
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
this.aspectJAdviceMethod + "]; pointcut expression [" +
this.pointcut.getPointcutExpression() + "]", ex);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}