上一节分析到 invoke方法主要有两行代码
1.获取Interceptor chain
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
2.执行advice的调用
retVal = invocation.proceed(); 执行Interceptor链 这里是一个递归的过程
这里继续分析invocation.proceed()
显示创建一个ReflectiveMethodInvocation对象 然后执行它的proceed方法
org.springframework.aop.framework. ReflectiveMethodInvocation 是AOP联盟的标准接口org.aopalliance.intercept.MethodInvocation的一个实现
public Object proceed() throws Throwable { //currentInterceptorIndex 初始值是-1 每次处理一个Interceptor 就会++ 最后相等的话 就说明Interceptor处理完了 就可以使用 //invokeJoinpoint 调用真实目标对象的方法了 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } //获取一个Interceptor 同时currentInterceptorIndex 会++ Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); //我们的不是InterceptorAndDynamicMethodMatcher 所以都是直接到else的 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); } } else { //这里就开始递归了 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
如果是前置通知 就是先执行advice的before方法 然后继续做proceed();递归下去
此时你的前置advice里面的逻辑已经被执行
public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); }
如果是后置通知
就是先进入下一层的proceed(); this.advice.afterReturning( )是先不执行的 等到proceed( )递归到出口了 执行完了以后一层层的返回的时候 this.advice.afterReturning( )才会执行
而递归的出口 就是真实target的方法被调用的时候
public Object invoke(MethodInvocation mi) throws Throwable { Object retVal = mi.proceed(); this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); return retVal; }
我们假设已经到了最后一层的proceed()方法 此时Interceptor已经处理完了
那么proceed()方法重 this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1就会为true
于是执行invokeJoinpoint()方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } protected Object invokeJoinpoint() throws Throwable { return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments); }
这个方法在 AopUtils里面了 public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args) throws Throwable { // Use reflection to invoke the method. try { ReflectionUtils.makeAccessible(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); } }
至此 target的方法也得到了调用
然后proceed( )方法会一层一层的返回 然后后置通知的afterReturning方法也就得到调用
public Object invoke(MethodInvocation mi) throws Throwable { Object retVal = mi.proceed(); this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); return retVal; }
这样一来 你的前置通知 后置通知 和 target原始方法 都得到了调用
这里 处理最巧妙的 还是
org.springframework.aop.framework.ReflectiveMethodInvocation 里的 proceed()方法
通过this.currentInterceptorIndex 来控制递归 每处理一个Interceptor 就增加1 等Interceptor处理完毕以后
就结束递归 进入joinpointInvoke()方法 去调用真实的target方法
我们的前置通知是MethodBeforeAdviceInterceptor类的实例 它的invoke方法是先调用advice的before()方法 执行前置通知的代码
然后重新进入proceed方法
我们的后置通知是AfterReturningAdviceInterceptor类的实例 它的invoke方法是调用proceed进入 进入下一层递归 等到递归结束,真实target对象的方法执行完了
返回回来的时候 才执行advice的aterReturning方法 执行后置通知的代码
通过这样一个逻辑 spring很巧妙的实现了在target目标方法调用前 依次执行了前置advice , 在target方法调用之后 依次执行了后置advice
从而实现了AOP的切面关注点的代码织入.
这次分析的是jdk动态代理实现的AOP 而且只分析了前置 后置 ,没有分析异常的advice处理
下次会专门分析一下看ThrowsAdvice的处理
以及cglibAop的处理逻辑