I'm trying to define a pointcut around a method annotated with a custom annotation. The annotation has one parameter that I would like to include a check in the pointcut definition.
This is the annotation:
public @interface MyAnno {
String[] types;
}
An example of how the annotation could be applied:
public class MyClass {
@MyAnno(types={"type1", "type2"})
public void doSomething() {
// ...
}
@MyAnno(types={"type3"})
public void doSomethingElse() {
// ...
}
}
Now I would like to have two pointcut definitions which select those two methods, based on the contents of the annotation.
Creating a pointcut on the annotation itself is relatively easy:
@Pointcut("@annotation(myAnno)")
public void pointcutAnno(MyAnno myAnno) {
}
@Pointcut("execution(* *(..)) && pointcutAnno(myAnno)")
public void pointcut(MyAnno myAnno) {
}
This will match every occurrence of the of @MyAnno. But how can I define two pointcuts, one matching @MyAnno
with types
containing "type1"
and the other matching @MyAnno
with types
containing "type3"
Currently AspectJ supports annotation value matching for a subset of the allowed kinds of annotation value. Unfortunately the array type you are using is not supported (class isn't supported either). This feature is documented in the 1.6.0 AspectJ README (https://eclipse.org/aspectj/doc/released/README-160.html). There is a section on 'Annotation value matching'. As described there the syntax is actually quite intuitive for the basic cases:
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);
}
}
So just include the value you want to match on in the annotation. Unfortunately the array case is more complicated and so not implemented yet. It needs a little more syntax to allow you to specify whether your pointcut means 'at least this in the array value' or 'exactly this and only this in the array value'. Presumably that would reuse ..
notation, something like this maybe:
execution(@MyAnno(types={"type1"}) * *(..)) { // exactly and only 'type1'
execution(@MyAnno(types={"type1",..}) * *(..)) { // at least 'type1'
Without the language support I'm afraid you do have to programmatically dig through the annotation in your code to check if it matches your constraint.