我正在尝试围绕使用自定义注释注释的方法定义切入点。注释有一个参数,我想在切入点定义中包含一个检查。
这是注释:
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
与types
包含"type1"
,另一个匹配@MyAnno
与types
包含"type3"
答案 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开始,您无法静态限制数组类型注释属性上的切入点表达式,就像使用非数组类型属性一样,因此此解决方案将涉及运行时测试。