【问题标题】:aspectj pointcut matching a specific annotation parameter value匹配特定注释参数值的 aspectj 切入点
【发布时间】:2017-11-23 15:39:24
【问题描述】:

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

这是注释:

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 的每次出现。但是我如何定义两个切入点,一个匹配@MyAnno 与包含"type1"types,另一个匹配@MyAnno 与包含typestypes

【问题讨论】:

    标签: java annotations aop aspectj


    【解决方案1】:

    目前,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'
    

    如果没有语言支持,恐怕您必须以编程方式挖掘代码中的注释以检查它是否符合您的约束。

    【讨论】:

    • 非常感谢您的想法。这对我帮助很大!我希望我没有看到进行数组匹配的方法。那么,运行时检查是必需的。但无论如何。非常感谢!
    【解决方案2】:

    您可以使用条件切入点来做到这一点,但这些将涉及对注解属性的运行时测试。

    原生方面语法:

    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 开始,您不能像使用非数组类型的属性那样静态限制数组类型注释属性上的切入点表达式,因此该解决方案将涉及运行时测试。

    【讨论】:

    • 也谢谢你!我想将两个评论标记为解决方案,但不幸的是 Stackoverflow 不允许我这样做。你解决这个问题的方法对我很有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-30
    • 1970-01-01
    • 2018-05-08
    • 2011-02-15
    • 2020-07-24
    • 1970-01-01
    相关资源
    最近更新 更多