拦截器链MethodInterceptor

ExposeInvocationInterceptor

MethodInvocation中封装了目标对象,目标方法,方法参数等信息。
ExposeInvocationInterceptor#invoke,只干了一件事就是将MethodInvocation加入到了ThreadLocal中,这样后续可以在其他地方使用ExposeInvocationInterceptor#currentInvocation获取到MethodInvocation

  1. private static final ThreadLocal<MethodInvocation> invocation =
  2. new NamedThreadLocal<>("Current AOP method invocation");
  3. public Object invoke(MethodInvocation mi) throws Throwable {
  4. MethodInvocation oldInvocation = invocation.get();
  5. invocation.set(mi);
  6. try {
  7. return mi.proceed();
  8. }
  9. finally {
  10. invocation.set(oldInvocation);
  11. }
  12. }

环绕通知的执行AspectJAroundAdvice

org.springframework.aop.aspectj.AspectJAroundAdvice#invoke

  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. if (!(mi instanceof ProxyMethodInvocation)) {
  3. throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
  4. }
  5. ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
  6. ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
  7. JoinPointMatch jpm = getJoinPointMatch(pmi);
  8. return invokeAdviceMethod(pjp, jpm, null, null);
  9. }

这里会去调用环绕通知的增强方法,而环绕通知的增强方法中会执行proceedingJoinPoint.proceed(),
这样就会调用下一个MethodInterceptor–>MethodBeforeAdviceInterceptor。

前置通知的执行MethodBeforeAdviceInterceptor

org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor
这里又会调用MethodInvocation.proceed()传递给下一个MethodInterceptor。

  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
  3. return mi.proceed();
  4. }

后置通知的执行AspectJAfterAdvice

org.springframework.aop.aspectj.AspectJAfterAdvice#invoke

  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. try {
  3. return mi.proceed();
  4. }
  5. finally {
  6. invokeAdviceMethod(getJoinPointMatch(), null, null);
  7. }
  8. }

先执行MethodInvocation.proceed(),最后在finally块中调用后置通知的增强,不管目标方法有没有抛出异常,finally代码块中的代码都会执行,也就是不管目标方法有没有抛出异常,后置通知都会执行。

返回后通知的执行AfterReturningAdviceInterceptor

org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor#invoke
先执行MethodInvocation.proceed(),然后再执行返回后通知的增强。

  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. Object retVal = mi.proceed();
  3. this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
  4. return retVal;
  5. }

异常通知的执行AspectJAfterThrowingAdvice

org.springframework.aop.aspectj.AspectJAfterThrowingAdvice#invoke
先执行MethodInvocation.proceed(),如果目标方法抛出了异常就会执行异常通知的增强,然后抛出异常

  1. public Object invoke(MethodInvocation mi) throws Throwable {
  2. try {
  3. return mi.proceed();
  4. }
  5. catch (Throwable ex) {
  6. if (shouldInvokeOnThrowing(ex)) {
  7. invokeAdviceMethod(getJoinPointMatch(), null, ex);
  8. }
  9. throw ex;
  10. }
  11. }

整个拦截链的过程

至最终,AOP拦截器的执行效果就会有两套:
目标方法正常执行:前置通知→目标方法→后置通知→返回通知
目标方法出现异常:前置通知→目标方法→后置通知→异常通知
image.png
整个拦截器链的执行过程,我们总结一下,其实就是链式获取每一个拦截器,然后执行拦截器的invoke()方法,
每一个拦截器等待下一个拦截器执行完成并返回以后,再来执行其invoke()方法。
通过拦截器链这种机制,保证了通知方法与目标方法的执行顺序。