`

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的一个实现

 

 

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    Spring API

    7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对类进行代理 7.5.6. 使用“全局”通知器 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动...

    Spring中文帮助文档

    7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对类进行代理 7.5.6. 使用“全局”通知器 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动...

    Spring-Reference_zh_CN(Spring中文参考手册)

    多application context情况下的处理 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ Load-time weaving(LTW) 6.9. 其它资源 7. Spring AOP APIs ...

    Spring 2.0 开发参考手册

    7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对类进行代理 7.5.6. 使用“全局”advisor 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动...

    spring chm文档

    7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对类进行代理 7.5.6. 使用“全局”advisor 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动...

Global site tag (gtag.js) - Google Analytics