步骤1
前面已经创建了MathCal的代理对象了,我们在调用方法时加一个断点
这里返回的确实是代理对象,这个对象中保存了详细信息(增强器,原始对象等),我们进入bean.add(2, 10) 中,来到
org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor.intercept(Object, Method, Object[], MethodProxy)方法,
拦截目标方法的执行
根据ProxyFactory获得目标方法的拦截器链,如果没有拦截器链,就直接执行目标方法
如果有拦截器链,将需要执行的目标对象,目标方法,连接器链传入,创建一个CglibMethodInvocation对象并调用proceed()方法
那么拦截器链如何获取呢?我们进入this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)方法中
通过advisorChainFactory获得目标方法的拦截器链,进入this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass)中
先创建一个list保存所有拦截器,可以看到,list创建时,已经初始化长度,这个长度就是通知方法的个数+一个默认通知,对于本案例就是5个。
之后又在循环遍历所有增强器,调用registry.getInterceptors(advisor);将其增强器包装为Interceptor[]拦截器,那么是如何包装的呢?
进入到其中查看,其实很简单,首先判断增强器是不是MethodInterceptor,如果是就直接加入到list中,
如果不是就使用增强器的适配器AdvisorAdapter将增强器转为MethodInterceptor,之后转为数组返回。
foreach循环完后就获得了拦截器链(每一个通知方法又被包装为拦截器,利用MethodInterceptor机制)
步骤2
获得了拦截器链,拦截器链是如何执行的呢?获得拦截器链后有new了一个CglibMethodInvocation并调用了proceed()方法
我们进入到proceed()方法
this.currentInterceptorIndex 表示执行的拦截器索引默认等于-1,首先判断是否有拦截器执行目标方法,
或者拦截器索引等于拦截器数组大小减一相等(也就是执行到最后一个拦截器)都会执行目标方法。下面我们debug调试,查看拦截器的执行
首先来到第一个拦截器
拦截器索引等于-1,拦截器数组等于4,通过this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
获得到第一个拦截器,拦截器索引+1,执行interceptorOrInterceptionAdvice).invoke(this)方法,传入的this为ChlibProxy
进入其中
其中invocation是当前线程共享的MethodInvocation,先从其中获得MethodInvocation,再将ChlibProxy加入到当前线程公享数据中,
调用ChlibProxy的procees()方法,进入mi.proceed()中,又来到我们之前的proceed()方发,初始的拦截器索引+1了
然后又重this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);获得第二个拦截器
之后又会调用((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);来到AspectJAfterThrowingAdvice的invoke()方法中
又是调用mi.proceed()方法,又来到proceed()方法,拦截器索引+1,又获的一个拦截器
AfterReturningAdviceInterceptor这个拦截器还是调用((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)方法,进入其中
又调用mi.proceed()方法,来到proceed(),拦截器索引+1,获得一个拦截器
又调用((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)方法,进入其中
又调用mi.proceed()来到proceed()方法,拦截器索引+1,获得一个拦截器
又调用((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)方法,进入其中
这里就调用了前置通知,之后又调用mi.proceed()来到proceed()方法
此时拦截器索引为4,等于拦截器数组大小4,就调用invokeJoinpoint()方法,执行目标方法并返回,之后就调用后置通知
后置通知调用完毕如果有异常就将异常向上抛,执行异常通知
如果没有异常,就执行返回通知
返回通知执行完毕,程序也就跑完了。拦截器链就是链式或去拦截器,调用拦截器的invoke()方法,
每一个拦截器都等待下一个拦截器执行完毕返回以后,在执行。通过拦截器链的机制,保证通知方法与目标方法的执行顺序。
步骤3,拦截器链调用过程