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

发布于 2022-09-05 22:46:14 字数 789 浏览 13 评论 0

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

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


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

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

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

双手揣兜 2022-09-12 22:46:14

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)的先执行.

茶花眉 2022-09-12 22:46:14

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

<aop:aspectj-autoproxy  /> 

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文