前言 在spring AOP中有这样五个advice:
Around
Before
After
AfterReturning
AfterThrowing
区别 我们直接从源码来看看这五种advice的区别吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 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 ); } public Object invoke (MethodInvocation mi) throws Throwable { this .advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); } public Object invoke (MethodInvocation mi) throws Throwable { try { return mi.proceed(); } finally { invokeAdviceMethod(getJoinPointMatch(), null , null ); } } public Object invoke (MethodInvocation mi) throws Throwable { Object retVal = mi.proceed(); this .advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); return retVal; } public Object invoke (MethodInvocation mi) throws Throwable { try { return mi.proceed(); } catch (Throwable t) { if (shouldInvokeOnThrowing(t)) { invokeAdviceMethod(getJoinPointMatch(), null , t); } throw t; } }
在这五种advice中,我们可以看出除了Around之外,其他都会回调mi.proceed方法。而Around则可以非常自由,甚至可以完全阻断原方法的执行(同时还会阻断Before的执行)。
对于After系列的方法,我们可以发现AfterReturning和AfterThrowing的执行条件是一种互补的关系,而After则无论如何都会执行。
执行顺序 我们在shouldSkip获取advisors的过程中会调用ReflectiveAspectJAdvisorFactory的getAdvisorMethods方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 private List<Method> getAdvisorMethods (Class<?> aspectClass) { final List<Method> methods = new LinkedList<Method>(); ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() { @Override public void doWith (Method method) throws IllegalArgumentException { if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null ) { methods.add(method); } } }); Collections.sort(methods, METHOD_COMPARATOR); return methods; }
在这段代码中我们可以发现其中有一个排序的过程,我们找到METHOD_COMPARATOR的定义(仍然在ReflectiveAspectJAdvisorFactory类中),可以看到如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 private static final Comparator<Method> METHOD_COMPARATOR;static { CompoundComparator<Method> comparator = new CompoundComparator<Method>(); comparator.addComparator(new ConvertingComparator<Method, Annotation>( new InstanceComparator<Annotation>( Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class), new Converter<Method, Annotation>() { @Override public Annotation convert (Method method) { AspectJAnnotation<?> annotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method); return annotation == null ? null : annotation.getAnnotation(); } })); comparator.addComparator(new ConvertingComparator<Method, String>( new Converter<Method, String>() { @Override public String convert (Method method) { return method.getName(); } })); METHOD_COMPARATOR = comparator; }
其中比较器使用的是InstanceComparator,初始化参数为Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class。我们打开InstanceComparator,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class InstanceComparator <T > implements Comparator <T > { private Class<?>[] instanceOrder; public InstanceComparator (Class<?>... instanceOrder) { Assert.notNull(instanceOrder, "InstanceOrder must not be null" ); this .instanceOrder = instanceOrder; } @Override public int compare (T o1, T o2) { int i1 = getOrder(o1); int i2 = getOrder(o2); return (i1 < i2 ? -1 : (i1 == i2 ? 0 : 1 )); } private int getOrder (T object) { if (object != null ) { for (int i = 0 ; i < instanceOrder.length; i++) { if (instanceOrder[i].isInstance(object)) { return i; } } } return instanceOrder.length; } }
可以看到比较顺序是由参数的传递顺序决定的。
但其实到这里我们仍然不能说advice的执行顺序是Around$\rightarrow$BeforeAfter$\rightarrow$AfterReturning$\rightarrow$AfterThrowing。
为什么呢?
如果我们仔细想一想After系列的代码,After系列函数的代码是先执行proceed再执行本身的。
那么这样的话,如果按照上面所说的顺序的话,最后执行出来的结果应该是Around$\rightarrow$Before$\rightarrow$AfterThrowing$\rightarrow$AfterReturning$\rightarrow$After。那么其实这样的顺序是不正确的,上面所说的那个顺序才是正确的。
不过,其实排序的部分并不止这一部分,我们直接找到AspectJPrecedenceComparator这个类,找到里面的compare方法,
1 2 3 4 5 6 7 public int compare (Advisor o1, Advisor o2) { int advisorPrecedence = this .advisorComparator.compare(o1, o2); if (advisorPrecedence == SAME_PRECEDENCE && declaredInSameAspect(o1, o2)) { advisorPrecedence = comparePrecedenceWithinAspect(o1, o2); } return advisorPrecedence; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 private int comparePrecedenceWithinAspect (Advisor advisor1, Advisor advisor2) { boolean oneOrOtherIsAfterAdvice = (AspectJAopUtils.isAfterAdvice(advisor1) || AspectJAopUtils.isAfterAdvice(advisor2)); int adviceDeclarationOrderDelta = getAspectDeclarationOrder(advisor1) - getAspectDeclarationOrder(advisor2); if (oneOrOtherIsAfterAdvice) { if (adviceDeclarationOrderDelta < 0 ) { return LOWER_PRECEDENCE; } else if (adviceDeclarationOrderDelta == 0 ) { return SAME_PRECEDENCE; } else { return HIGHER_PRECEDENCE; } } else { if (adviceDeclarationOrderDelta < 0 ) { return HIGHER_PRECEDENCE; } else if (adviceDeclarationOrderDelta == 0 ) { return SAME_PRECEDENCE; } else { return LOWER_PRECEDENCE; } } }
可以看到这部分,对于After系列的advice,它会进行反序,由于前面排序调用涉及的方法比较多,此处不详解。
最后的结果就是拦截器最终排出来的顺序是AfterThrowing$\rightarrow$AfterReturning$\rightarrow$After$\rightarrow$Around$\rightarrow$Before。
这样的话,根据递归的逻辑,最终advice的执行顺序便为Around$\rightarrow$Before$\rightarrow$After$\rightarrow$AfterReturning$\rightarrow$AfterThrowing。
其中Around会阻断Before的执行,但是不能阻断After系列advice的执行。