jdk动态代理的情况下 前后置advice的调用过程分析 part2

上一节分析到 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的一个实现

 

扫描二维码关注公众号,回复: 502032 查看本文章

 

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的处理逻辑

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

猜你喜欢

转载自wangzheng1989.iteye.com/blog/2172969