欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

spring5 源码深度解析----- AOP目标方法和增强方法的执行(100%理解AOP)

程序员文章站 2024-01-28 12:24:10
上一篇博文中我们讲了代理类的生成,这一篇主要讲解剩下的部分,当代理类调用时,目标方法和代理方法是如何执行的,我们还是接着上篇的ReflectiveMethodInvocation类Proceed方法来看 我们先来看一张方法调用顺序图 我们看到链中的顺序是AspectJAfterThrowingAdv ......

上一篇博文中我们讲了代理类的生成,这一篇主要讲解剩下的部分,当代理类调用时,目标方法和代理方法是如何执行的,我们还是接着上篇的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);
    }
}

我们先来看一张方法调用顺序图

spring5 源码深度解析----- AOP目标方法和增强方法的执行(100%理解AOP)

我们看到链中的顺序是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这几个拦截器,在拦截器中反射调用增强方法