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 {
		//	We start with an index of -1 and increment early.
       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 {
			// It's an interceptor, so we just invoke it: The pointcut will have
			// been evaluated statically before this object was constructed.
            这里就开始递归了
			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,动态代理,AOP,Interceptor,advice,Advisor)