1. 程式人生 > >spring5 原始碼深度解析----- AOP目標方法和增強方法的執行(100%理解AOP)

spring5 原始碼深度解析----- AOP目標方法和增強方法的執行(100%理解AOP)

上一篇博文中我們講了代理類的生成,這一篇主要講解剩下的部分,當代理類呼叫時,目標方法和代理方法是如何執行的,我們還是接著上篇的ReflectiveMethodInvocation類Proceed方法來看

public Object proceed() throws Throwable {
    // 首先,判斷是不是所有的interceptor(也可以想像成advisor)都被執行完了。
    // 判斷的方法是看currentInterceptorIndex這個變數的值,增加到Interceptor總個數這個數值沒有,
    // 如果到了,就執行被代理方法(invokeJoinpoint());如果沒到,就繼續執行Interceptor。
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return invokeJoinpoint();
    }

    // 如果Interceptor沒有被全部執行完,就取出要執行的Interceptor,並執行。
    // currentInterceptorIndex先自增
     Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    // 如果Interceptor是PointCut型別
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
        InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
        // 如果當前方法符合Interceptor的PointCut限制,就執行Interceptor
        if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
           // 這裡將this當變數傳進去,這是非常重要的一點
            return dm.interceptor.invoke(this);
        }
        // 如果不符合,就跳過當前Interceptor,執行下一個Interceptor
        else {
            return proceed();
        }
    }
    // 如果Interceptor不是PointCut型別,就直接執行Interceptor裡面的增強。
    else {
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

我們先來看一張方法呼叫順序圖

我們看到鏈中的順序是AspectJAfterThrowingAdvice、AfterReturningAdviceInterceptor、AspectJAfterAdvice、MethodBeforeAdviceInterceptor,這些攔截器是按順序執行的,那我們來看看第一個攔截器AspectJAfterThrowingAdvice中的invoke方法

AspectJAfterThrowingAdvice

 1 @Override
 2 public Object invoke(MethodInvocation mi) throws Throwable {
 3     try {
 4         //直接呼叫MethodInvocation的proceed方法
 5         //從proceed()方法中我們知道dm.interceptor.invoke(this)傳過來的引數就是ReflectiveMethodInvocation執行器本身
 6         //這裡又直接呼叫了ReflectiveMethodInvocation的proceed()方法
 7         return mi.proceed();
 8     }
 9     catch (Throwable ex) {
10         if (shouldInvokeOnThrowing(ex)) {
11             invokeAdviceMethod(getJoinPointMatch(), null, ex);
12         }
13         throw ex;
14     }
15 }

第一個攔截器AspectJAfterThrowingAdvice的invoke方法中,直接呼叫mi.proceed();,從proceed()方法中我們知道dm.interceptor.invoke(this)傳過來的引數就是ReflectiveMethodInvocation執行器本身,所以又會執行proceed()方法,攔截器下標currentInterceptorIndex自增,獲取下一個攔截器AfterReturningAdviceInterceptor,並呼叫攔截器中的invoke方法,,此時第一個攔截器在invoke()方法的第七行卡住了,接下來我們看第二個攔截器的執行

AfterReturningAdviceInterceptor

1 @Override
2 public Object invoke(MethodInvocation mi) throws Throwable {
3     //直接呼叫MethodInvocation的proceed方法
4     Object retVal = mi.proceed();
5     this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
6     return retVal;
7 }

AfterReturningAdviceInterceptor還是直接呼叫mi.proceed(),又回到了ReflectiveMethodInvocation的proceed()方法中,此時AfterReturningAdviceInterceptor方法卡在第四行,接著回到ReflectiveMethodInvocation的proceed()方法中,攔截器下標currentInterceptorIndex自增,獲取下一個攔截器AspectJAfterAdvice,並呼叫AspectJAfterAdvice中的invoke方法

AspectJAfterAdvice

 1 @Override
 2 public Object invoke(MethodInvocation mi) throws Throwable {
 3     try {
 4         //直接呼叫MethodInvocation的proceed方法
 5         return mi.proceed();
 6     }
 7     finally {
 8         invokeAdviceMethod(getJoinPointMatch(), null, null);
 9     }
10 }

AspectJAfterAdvice還是直接呼叫mi.proceed(),又回到了ReflectiveMethodInvocation的proceed()方法中,此時AspectJAfterAdvice方法卡在第五行,接著回到ReflectiveMethodInvocation的proceed()方法中,攔截器下標currentInterceptorIndex自增,獲取下一個攔截器MethodBeforeAdviceInterceptor,並呼叫MethodBeforeAdviceInterceptor中的invoke方法

MethodBeforeAdviceInterceptor

1 @Override
2 public Object invoke(MethodInvocation mi) throws Throwable {
3     //終於開始做事了,呼叫增強器的before方法,明顯是通過反射的方式呼叫
4     //到這裡增強方法before的業務邏輯執行
5     this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
6     //又呼叫了呼叫MethodInvocation的proceed方法
7     return mi.proceed();
8 }

第5行程式碼終於通過反射呼叫了切面裡面的before方法,接著又呼叫mi.proceed(),我們知道這是最後一個攔截器了,此時this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1應該為true了,那麼就會執行 return invokeJoinpoint();,也就是執行bean中的目標方法,接著我們來看看目標方法的執行

@Nullable
protected Object invokeJoinpoint() throws Throwable {
    return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}

    @Nullable
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
        throws Throwable {

    // Use reflection to invoke the method.
    try {
        ReflectionUtils.makeAccessible(method);
        //直接通過反射呼叫目標bean中的method
        return method.invoke(target, args);
    }
    catch (InvocationTargetException ex) {
        // Invoked method threw a checked exception.
        // We must rethrow it. The client won't see the interceptor.
        throw ex.getTargetException();
    }
    catch (IllegalArgumentException ex) {
        throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
                method + "] on target [" + target + "]", ex);
    }
    catch (IllegalAccessException ex) {
        throw new AopInvocationException("Could not access method [" + method + "]", ex);
    }
}

before方法執行完後,就通過反射的方式執行目標bean中的method,並且返回結果,接下來我們想想程式該怎麼執行呢?

1 、MethodBeforeAdviceInterceptor執行完了後,開始退棧,AspectJAfterAdvice中invoke卡在第5行的程式碼繼續往下執行, 我們看到在AspectJAfterAdvice的invoke方法中的finally中第8行有這樣一句話 invokeAdviceMethod(getJoinPointMatch(), null, null);,就是通過反射呼叫AfterAdvice的方法,意思是切面類中的 @After方法不管怎樣都會執行,因為在finally中

 2、AspectJAfterAdvice中invoke方法發執行完後,也開始退棧,接著就到了AfterReturningAdviceInterceptor的invoke方法的第4行開始恢復,但是此時如果目標bean和前面增強器中出現了異常,此時AfterReturningAdviceInterceptor中第5行程式碼就不會執行了,直接退棧;如果沒有出現異常,則執行第5行,也就是通過反射執行切面類中@AfterReturning註解的方法,然後退棧

3、AfterReturningAdviceInterceptor退棧後,就到了AspectJAfterThrowingAdvice攔截器,此攔截器中invoke方法的第7行開始恢復,我們看到在 catch (Throwable ex) { 程式碼中,也就是第11行 invokeAdviceMethod(getJoinPointMatch(), null, ex);,如果目標bean的method或者前面的增強方法中出現了異常,則會被這裡的catch捕獲,也是通過反射的方式執行@AfterThrowing註解的方法,然後退棧

總結

這個代理類呼叫過程,我們可以看到是一個遞迴的呼叫過程,通過ReflectiveMethodInvocation類中Proceed方法遞迴呼叫,順序執行攔截器鏈中AspectJAfterThrowingAdvice、AfterReturningAdviceInterceptor、AspectJAfterAdvice、MethodBeforeAdviceInterceptor這幾個攔截器,在攔截器中反射呼叫增強方法

 

&n