在使用Spring AOP时,有时会有在同一切入点存在多个Advice的情况出现,这里的多个Advice可能是不同的Advice,比如后置增强和环绕增强,也可能是多个相同的Advice,比如多个后置增强,甚至是更复杂的情况。因而就存在一个需求:不同Advice的执行顺序是怎样的,同样类型的Advice如何排序,一步一步来看。
 1.Advice的执行顺序
 对于不同类型的Advice执行顺序,大家都比较熟悉,但是为了比较更复杂的情况,还是先简单介绍下。
 不同类型的Advice
 Spring AOP中定义的基本增强有五种,分别是前置增强(BeforeAdvice),后置增强(AfterReturningAdvice),后置finally增强(AfterAdvice),抛出增强(AfterThrowingAdvice)和环绕增强(AroundAdvice)。
 由于环绕增强可以通过ProceedingJoinPoint调用proceed方法执行原始方法,因此环绕增强可以分为环绕增强前(around before)和环绕增强后(around after),对应proceed方法的前后。
 后置增强为return操作后操作,抛出增强为异常抛出时操作,故这两者是互斥的。后置finally增强,是finally类型的操作,因而不论方法是否有异常,都会执行,且在后置增强和抛出增强前执行。
 用代码定义下以上Advice
 // 环绕增强 @Around("pointcut()") public Object around(ProceedingJoinPoint pjp) throws Throwable{ 	System.out.println("around before"); 	Object retVal = pjp.proceed(); 	System.out.println("around after"); 	return retVal; }  // 前置增强 @Before("pointcut()") public void before(){ 	System.out.println("before"); }  // 后置finally增强 @After("pointcut()") public void after(){ 	System.out.println("after"); }  // 后置return增强 @AfterReturning("pointcut()") public void afterReturning(){ 	System.out.println("after returning"); }  // 抛出增强 @AfterThrowing(value="pointcut()",throwing="ex") public void afterThrowing(Exception ex){ 	System.out.println("afterThrowing"); } 
 通过测试执行的结果为
 around before before //method execute around after after after returning 
 如果方法抛出异常,结果为
 around before before //method execute after afterThrowing 
 因而对于五种增强类型的执行顺序如下
  - 环绕增强前(around advice before)
- 前置增强(before advice)
- -- 方法执行
- 环绕增强后(around advice after)
- 后置finally增强(after advice)
- 后置增强/抛出增强
相同类型Advice的排序
 如果存在两个相同类型的Advice,如何进行排序?答案Spring AOP不支持Advice层级的排序,只支持Aspect层级的排序。不同的Aspect通过实现Ordered接口,或使用@Order注解设置优先级。对于getOrder返回的值或@Order中设置的值,值越小优先级越高。
 @Aspect public class AspectJAspect implements Ordered{ 	@Override 	public int getOrder() { 		return 1; 	} } 
 或者
 @Aspect @Order(1) public class AspectJAspect{ } 
 而多个Aspect中的相同类型Advice执行顺序,也分为两种情况:
  - 方法执行之前的增强Advice,优先级高的先执行,如前置增强
- 方法执行之后的增强Advice,优先级高的后执行,如后置增强
且对于多个不同排序的Aspect中的多个Advice,一个Aspect执行完才到下一个Aspect,同样也是以原始方法的执行为界。
 还以上面的多个Advice代码为例,如果存在两个Aspect,分别标注@Order(1)和@Order(2),@Order(1)对应的Advice打印内容后加1,@Order(2)对应的加2。以前置增强举例:
 @Aspect @Order(1) public class AspectJAspect1{ 	@Before("pointcut()") 	public void before(){ 		System.out.println("before 1"); 	} }  @Aspect @Order(2) public class AspectJAspect2{ 	@Before("pointcut()") 	public void before(){ 		System.out.println("before 2"); 	} } 
 经过测试,打印结果如下:
 around before 1 before 1 around before 2 before 2 // method execute around after 2 after 2 after returning 2 around after 1 after 1 after returning 1 
 对于这个测试结果,以后有类似的实现时还是要多注意的。至于原理,一是创建代理时形成的拦截器的链式调用,可见ReflectiveMethodInvocation的proceed方法,二是创建同一Aspect内的Advice有一个默认的排序方式,见ReflectiveAspectJAdvisorFactory中static代码库的METHOD_COMPARATOR创建。
 2.@Order原理解析
 Aspect类的排序,通过Ordered接口或@Order注解来实现。而注解情况下,获取完全部的Advice并封装成Advisor后,使用模板方法sortAdvisors完成了排序。
 AbstractAdvisorAutoProxyCreator中的默认实现如下
 protected List<Advisor> sortAdvisors(List<Advisor> advisors) { 	OrderComparator.sort(advisors); 	return advisors; } 
 OrderComparator是Comparator的子类,通过compare方法比较两个对象
 public int compare(Object o1, Object o2) { 	return doCompare(o1, o2, null); }  private int doCompare(Object o1, Object o2, OrderSourceProvider sourceProvider) { 	boolean p1 = (o1 instanceof PriorityOrdered); 	boolean p2 = (o2 instanceof PriorityOrdered); 	if (p1 && !p2) { 		return -1; 	} 	else if (p2 && !p1) { 		return 1; 	}  	// Direct evaluation instead of Integer.compareTo to avoid unnecessary object creation. 	int i1 = getOrder(o1, sourceProvider); 	int i2 = getOrder(o2, sourceProvider); 	return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0; } 
 如果有Advisor实现了PriorityOrdered,而另一个没有实现,则实现PriorityOrdered的优先级更高。如果两个都没有实现PriorityOrdered,则继续比较getOrder方法返回的值。
 private int getOrder(Object obj, OrderSourceProvider sourceProvider) { 	Integer order = null; 	if (sourceProvider != null) { 		order = findOrder(sourceProvider.getOrderSource(obj)); 	} 	return (order != null ? order : getOrder(obj)); }  protected int getOrder(Object obj) { 	Integer order = findOrder(obj); 	return (order != null ? order : Ordered.LOWEST_PRECEDENCE); }  protected Integer findOrder(Object obj) { 	return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null); } 
 如果Advisor实现了Ordered接口,则调用getOrder()方法,如果没实现,返回Ordered.LOWEST_PRECEDENCE,即Integer.MAX_VALUE。
 到此排序的思路基本清晰了,但是突然发现一个问题,使用@Order的Aspect并没有实现Ordered接口啊,这里不是挂了吗?
 这时回头看下sortAdvisors方法,进行排序的都是Advisor,并不是Aspect。而AspectJ方式的AOP,都是通过硬编码的方式指定了实际的Advisor类。XML方式的是AspectJPointcutAdvisor,注解方式的是InstantiationModelAwarePointcutAdvisorImpl,而这两个类都实现了Ordered接口。
 注解方式的InstantiationModelAwarePointcutAdvisorImpl,其getOrder方法如下
 public int getOrder() { 	return this.aspectInstanceFactory.getOrder(); } 
 这里的aspectInstanceFactory的类型为MetadataAwareAspectInstanceFactory,其实际的实现类为BeanFactoryAspectInstanceFactory,其为Aspect实例的工厂类
 public int getOrder() { 	Class<?> type = this.beanFactory.getType(this.name); 	if (type != null) { 		if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) { 			return ((Ordered) this.beanFactory.getBean(this.name)).getOrder(); 		} 		// Aspect非Ordered实现时处理 		return OrderUtils.getOrder(type, Ordered.LOWEST_PRECEDENCE); 	} 	return Ordered.LOWEST_PRECEDENCE; } 
 这里对Aspect类未实现Ordered接口进行了处理,查询Aspect是否有@Order注解,如果存在则返回其value值。另外如果不存在@Order,再去查询是否有javax.annotation.Priority注解,这是java通用注解包里支持优先级的注解。
 public static Integer getOrder(Class<?> type, Integer defaultOrder) { 	Order order = AnnotationUtils.findAnnotation(type, Order.class); 	if (order != null) { 		return order.value(); 	} 	Integer priorityOrder = getPriority(type); 	if (priorityOrder != null) { 		return priorityOrder; 	} 	return defaultOrder; } 
 3.AspectJ方式的Advisor排序
 在AOP AspectJ方式的驱动类AspectJAwareAdvisorAutoProxyCreator中,重写了sortAdvisors方法,使用AspectJPrecedenceComparator比较器代替之前的OrderComparator,但其内部实现还是使用OrderComparator,只是在优先级一样且是同一个Aspect时,对Advice的declarationOrder进行排序。declarationOrder目前并不能进行配置,而只是通过ReflectiveAspectJAdvisorFactory中的METHOD_COMPARATOR按规则对Advice赋值。