spring aop的order执行顺序的奇怪现象

以我所知:用注解order可以用来控制aop的执行顺序。则是按照1>2>3这个顺序执行。

但是我这个例子却很奇怪,并不是按照这个顺序执行。


order1这个类,有2个around方式的拦截,一个是拦截注解,一个是拦截方法
图片描述

order2这个类,和order1中的拦截方法,是同一个拦截方式
图片描述

我理想中的执行顺序,应该是:order1拦截注解 > order1拦截方法 > order2拦截方法
但是实际的执行顺序,却是:order1拦截注解 > order2拦截方法 > order1拦截方法

于是我发现,无论如何设置order,必然都一定是拦截注解会先执行。
所以这个现象究竟应该如何解释?难道是那个什么先执行的后返回?但是我这里没用到before和after啊

回答:

Spring的AOP执行顺序的参考文档如下:
http://docs.spring.io/spring/...
简单的说,@Aspect注解的Order是起效的,但同一个Aspect中的Advice是没有明确的执行顺序的,例如你Order(1)中的两个Advice.我们看以参考ReflectiveAspectJAdvisorFactory类的源码如下:

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 ? annotation.getAnnotation() : null);

}

}));

comparator.addComparator(new ConvertingComparator<Method, String>(

new Converter<Method, String>() {

@Override

public String convert(Method method) {

return method.getName();

}

}));

METHOD_COMPARATOR = comparator;

}

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {

Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();

String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();

validate(aspectClass);

// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator

// so that it will only instantiate once.

MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =

new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

List<Advisor> advisors = new LinkedList<Advisor>();

for (Method method : getAdvisorMethods(aspectClass)) {

Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);

if (advisor != null) {

advisors.add(advisor);

}

}

我们可以看到,其实Spring也就是按照方法名的对同级别Advice进行排序的.所以,如果想让同级别advice顺序执行,最好的办法就是,方法名按英文字母排列.我的测试代码如下:

@Around(value = "execution(* org.sagesource..*.*(..))")

public Object aheckAuthPackage(ProceedingJoinPoint joinPoint) throws Throwable {

System.out.println("----Order1:checkAuthPackage:Execution----");

Object[] args = joinPoint.getArgs();

return joinPoint.proceed(args);

}

@Around(value = "@annotation(org.sagesource.training.spring.aop.order.annotation.AuthAnnotation)")

public Object checkAuth(ProceedingJoinPoint joinPoint) throws Throwable {

System.out.println("----Order1:checkAuth:Annotation----");

Object[] args = joinPoint.getArgs();

return joinPoint.proceed(args);

}

执行结果:
----Order1:checkAuthPackage:Execution----
----Order1:checkAuth:Annotation----

但是楼主说的实际执行顺序应该还是不对的,肯定是Order(1)的先执行.

回答:

不能使用CGlib 去生成动态代理,使用JDK去生成代理,spring xml配置如下:

<aop:aspectj-autoproxy  /> 

之前配置如下Order 不起作用。换成上面的配置就好了.原因还不是很清楚,JDK生成的代理Debug 可以看到advisorArray,这个数组是排序后的advisor

<aop:aspectj-autoproxy  proxy-target-class="true"/>

以上是 spring aop的order执行顺序的奇怪现象 的全部内容, 来源链接: utcz.com/p/175460.html

回到顶部