拦截器链MethodInterceptor
ExposeInvocationInterceptor
MethodInvocation中封装了目标对象,目标方法,方法参数等信息。
ExposeInvocationInterceptor#invoke,只干了一件事就是将MethodInvocation加入到了ThreadLocal中,这样后续可以在其他地方使用ExposeInvocationInterceptor#currentInvocation获取到MethodInvocation
private static final ThreadLocal<MethodInvocation> invocation =
new NamedThreadLocal<>("Current AOP method invocation");
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
环绕通知的执行AspectJAroundAdvice
org.springframework.aop.aspectj.AspectJAroundAdvice#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
}
这里会去调用环绕通知的增强方法,而环绕通知的增强方法中会执行proceedingJoinPoint.proceed(),
这样就会调用下一个MethodInterceptor–>MethodBeforeAdviceInterceptor。
前置通知的执行MethodBeforeAdviceInterceptor
org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor
这里又会调用MethodInvocation.proceed()传递给下一个MethodInterceptor。
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
后置通知的执行AspectJAfterAdvice
org.springframework.aop.aspectj.AspectJAfterAdvice#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
先执行MethodInvocation.proceed(),最后在finally块中调用后置通知的增强,不管目标方法有没有抛出异常,finally代码块中的代码都会执行,也就是不管目标方法有没有抛出异常,后置通知都会执行。
返回后通知的执行AfterReturningAdviceInterceptor
org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor#invoke
先执行MethodInvocation.proceed(),然后再执行返回后通知的增强。
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
异常通知的执行AspectJAfterThrowingAdvice
org.springframework.aop.aspectj.AspectJAfterThrowingAdvice#invoke
先执行MethodInvocation.proceed(),如果目标方法抛出了异常就会执行异常通知的增强,然后抛出异常
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
整个拦截链的过程
至最终,AOP拦截器的执行效果就会有两套:
目标方法正常执行:前置通知→目标方法→后置通知→返回通知
目标方法出现异常:前置通知→目标方法→后置通知→异常通知
整个拦截器链的执行过程,我们总结一下,其实就是链式获取每一个拦截器,然后执行拦截器的invoke()方法,
每一个拦截器等待下一个拦截器执行完成并返回以后,再来执行其invoke()方法。
通过拦截器链这种机制,保证了通知方法与目标方法的执行顺序。