aspectj切入点匹配特定的注释参数值

时间:2017-11-23 15:39:25

标签: java annotations aop aspectj

我正在尝试围绕使用自定义注释注释的方法定义切入点。注释有一个参数,我想在切入点定义中包含一个检查。

这是注释:

public @interface MyAnno {
  String[] types;
}

如何应用注释的示例:

public class MyClass {
  @MyAnno(types={"type1", "type2"})
  public void doSomething() {
    // ...
  }
  @MyAnno(types={"type3"})
  public void doSomethingElse() {
    // ...
  }
}

现在我希望有两个切入点定义,根据注释的内容选择这两种方法。

在注释本身上创建切入点相对容易:

@Pointcut("@annotation(myAnno)")
public void pointcutAnno(MyAnno myAnno) {
}

@Pointcut("execution(* *(..)) && pointcutAnno(myAnno)")
public void pointcut(MyAnno myAnno) {
}

这将匹配@MyAnno的每次出现。但是,如何定义两个切入点,一个匹配@MyAnnotypes包含"type1",另一个匹配@MyAnnotypes包含"type3"

2 个答案:

答案 0 :(得分:2)

目前,AspectJ支持对允许种类的注释值的子集进行注释值匹配。不幸的是,不支持您使用的数组类型(类也不支持)。 1.6.0 AspectJ README(https://eclipse.org/aspectj/doc/released/README-160.html)中记录了此功能。有一个关于'注释值匹配的部分'。如上所述,语法实际上对于基本情况非​​常直观:

enum TraceLevel { NONE, LEVEL1, LEVEL2, LEVEL3 }

@interface Trace {
  TraceLevel value() default TraceLevel.LEVEL1;
}

aspect X {
  // Advise all methods marked @Trace except those with a tracelevel of none
  before(): execution(@Trace !@Trace(TraceLevel.NONE) * *(..)) {
    System.err.println("tracing "+thisJoinPoint);
  }
}

因此,只需在注释中包含要匹配的值即可。不幸的是阵列情况更复杂,因此尚未实现。它需要更多的语法,以允许您指定您的切入点是否至少意味着数组值中的这个'或者'恰好这个,只有这个在数组值'中。据推测,这将重用..符号,这样的事情可能是:

execution(@MyAnno(types={"type1"}) * *(..)) { // exactly and only 'type1'
execution(@MyAnno(types={"type1",..}) * *(..)) { // at least 'type1'

如果没有语言支持,我担心您必须以编程方式挖掘代码中的注释,以检查它是否与您的约束匹配。

答案 1 :(得分:1)

您可以使用条件切入点来执行此操作,但这些将涉及对注释属性的运行时测试。

原生方面语法:

pointcut p(MyAnno myAnno): execution(* *(..)) 
    && @annotation(myAnno) 
    && if(Arrays.stream(myAnno.types()).anyMatch("type1"::equals));

基于注释的方面语法:

@Pointcut("execution(* *(..)) && @annotation(myAnno) && if()")
public boolean pointcut(MyAnno myAnno) {
    return !Arrays.stream(myAnno.types()).anyMatch("type1"::equals);
}

不要忘记为这两个示例导入java.util.Arrays

目前,从AspectJ版本1.8.13开始,您无法静态限制数组类型注释属性上的切入点表达式,就像使用非数组类型属性一样,因此此解决方案将涉及运行时测试。