3

我无法以特定顺序触发多个方面。我正在使用 RequestProcessor 对控制器上的每个传入请求执行某些操作,这些请求具有特定参数

然后我有一些特定的注释,我将只添加到我的控制器中的某些方法中。

仅供参考,我正在使用 Eclipse、Tomcat、Maven 和 spring 以及基于 java/annotation 的配置。我使用 Tomcat 和 WebApplicationInitializer 来加载我的上下文、调度程序、侦听器等。我没有 web.xml。如果需要,我也可以发布它或 pom.xml。

我遇到的问题是,一个既满足ProcessRequest切入点又满足someAnnotation切入点的方法首先触发该someAnnotation方法,即使指定了首先触发的顺序ProcessRequest。中设置了ProcessRequest一些其他注释中需要的属性。

这是我的代码的简化版本。

Spring 配置类

@Configuration  // Enable Spring Annotation Configuration. Equivalent to <context:annotation-config/>
@EnableAspectJAutoProxy
@EnableCaching  // Enable Spring caching
@EnableWebMvc   // Enable Spring MVC Annotation. Equivalent to <mvc:annotation-driven />.
@ComponentScan(basePackages = {"xxx.yyy.zzz"}) // Scan for Spring Components.      Equivalent to <context:component-scan>
public class WebAppConfig extends WebMvcConfigurerAdapter {

    // Other Bean logic here

    @Bean
    public RequestProcessor requestProcessor() {
        return new RequestProcessor();
    }

    @Bean
    public AnnotationAspect annotationAspect() {
        return new AnnotationAspect();
    }
}

方面#1

@Aspect
@Order(0)
public class RequestProcessor {

    @Pointcut("execution(* xxx.yyy.zzz.api..*.*(xxx.yyy.zzz.objects.api.Request,..)) && args(request)")
    public void pointcut(Request<?> request) {}

    @Before("pointcut(request)")
    public void processRequest(Request<?> request) throws IOException, BadSignatureException {
        // Some logic here that is independent of other and needs to run before other aspect which references annotation
    }
}

方面#2

@Aspect
@Order(1)
public class AnnotationAspect {

    @Before("@annotation(xxx.yyy.zzz.annotation.SomeAnnotation)")
    public void someAnnotation() {
        // Log for this annotation
    }

    // Some other annotation methods here
}

也试过这种格式implements Ordered

@Aspect
public class RequestProcessor implements Ordered {

    @Override
    public int getOrder() {
        return 0;
    }

    @Pointcut("execution(* xxx.yyy.zzz.api..*.*(xxx.yyy.zzz.objects.api.Request,..)) && args(request)")
    public void pointcut(Request<?> request) {}

    @Before("pointcut(request)")
    public void processRequest(Request<?> request) throws IOException, BadSignatureException {
        // Some logic here that is independent of other and needs to run before other aspect which references annotation
    }
}

我阅读了这篇文章和其他一些文章,但找不到任何相关的内容。

Spring AOP && MVC 的排序方面

****更新****

所以我一直在阅读关于声明优先级的 AspectJ 文档,所以我想我会试一试。我创建了一个只声明优先级的简单方面,它工作得很好。

这是我的优先方面:

public aspect AspectPrecedence {
    declare precedence : RequestProcessor, SomeAspect;
}

我暂时不打算将此作为答案提交,因为我想了解为什么注释或“已订购的实现”在我的项目中无法正常运行。

任何见解将不胜感激。谢谢!

****更新2****

作为参考,这在我的 eclipse 环境中本地工作,并且在通过 WAR 文件部署到 AWS 时似乎工作。

@Aspect
@DeclarePrecedence("RequestProcessor, SomeAspect")
public class RequestProcessor {

    @Pointcut("execution(* xxx.yyy.zzz.api..*.*(xxx.yyy.zzz.objects.api.Request,..)) && args(request)")
    public void pointcut(Request<?> request) {}

    @Before("pointcut(request)")
    public void processRequest(Request<?> request) throws IOException, BadSignatureException {
        // Some logic here that is independent of other and needs to run before other aspect which references annotation
    }
}
4

2 回答 2

3

当使用带有 AspectJ 支持的 Eclipse 时,会在您的 IDE 中自动启用编译时编织。这意味着方面被编织到您的字节码中,而 Spring 使用代理来应用方面。

使用方面来声明优先级或使用@DeclarePrecedence仅在使用编译或加载时编织时才有效(后者可以通过指定来启用,具体<context:load-time-weaver/> 取决于您的容器可能需要一些额外的配置)。但是两者都应该工作(您可能需要将 AspectJ 编译器指定为 @Aspect 类的编译器,而不是默认的 java 编译器)。

@Order并且Ordered仅适用于基于代理的解决方案,并且被 AspectJ 忽略。

于 2013-11-01T19:19:23.373 回答
1

我认为问题可能是您使用带有 AspectJ 的 LTW 而不是带有 Spring 的 AOP,因为 @Order 是为 Spring 定义的,容器(AspectJ)无法确定这两个建议的顺序,所以请尝试以下之一:

  1. 尝试翻转@Aspect@Order注释的顺序
  2. 您可以尝试@DeclarePrecedence来自 AspectJ 的注释,然后将您的方面配置到 aop.xml
<aspects>        
        <aspect name="your.package.RequestProcessor"/>
        <aspect name="your.package.AnnotationAspect"/>
           <concrete-aspect name="my_aspect_configuration_precedence"
                precedence="*..*RequestProcessor, *"/>
</aspects>

我不知道它是否会起作用,但希望能给你一个指示

于 2013-10-31T18:56:36.827 回答