I have defined a meta annotation and a number of concrete annotations annotated with the meta. I am currently trying to implement an aspect that would weave methods annotated with these concrete annotations based on the meta annotation. I was able to use this pointcut to achieve the advice invocation.
"execution(@(@my.meta.Annotation *) * *(..))"
However, I would like to make use of parameter binding because the meta annotation defines a field whose value I am interested in. Unfortunatelly, I was not able to find a correct expression to achieve that.
Is it possible to use parameter binding when using a nested annotation pointcut or do I need to get the annotation from JoinPoint
?
Annotation binding via @annotation()
, @within()
needs an exact class, but you want a generic solution. Therefore, you do need to fetch the annotation from the method via reflection, i.e. you need to take the route:
joinpoint → signature → method → annotation → meta annotation
package de.scrum_master.stackoverflow.q75834894.app;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
@Retention(RUNTIME)
public @interface Meta {
String id();
}
package de.scrum_master.stackoverflow.q75834894.app;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
@Retention(RUNTIME)
@Meta(id = "indirect")
public @interface Marker {}
package de.scrum_master.stackoverflow.q75834894.app;
public class Application {
public static void main(String[] args) {
Application application = new Application();
application.notAnnotated();
application.metaAnnotated();
application.markerAnnotated();
}
public void notAnnotated() {}
@Meta(id = "direct") public void metaAnnotated() {}
@Marker public void markerAnnotated() {}
}
package de.scrum_master.stackoverflow.q75834894.aspect;
import java.lang.annotation.Annotation;
import org.aspectj.lang.reflect.MethodSignature;
import de.scrum_master.stackoverflow.q75834894.app.Meta;
public aspect MyAspect {
before(Meta meta) : @annotation(meta) && execution(* *(..)) {
System.out.println(thisJoinPoint);
System.out.println(" " + meta.id());
}
before() : execution(@(@de.scrum_master.stackoverflow.q75834894.app.Meta *) * *(..)) {
System.out.println(thisJoinPoint);
for (Annotation annotation : ((MethodSignature) thisJoinPoint.getSignature()).getMethod().getAnnotations()) {
Meta meta = annotation.annotationType().getAnnotation(Meta.class);
if (meta != null)
System.out.println(" " + meta.id());
}
}
}
I guess you know how how to convert the native syntax aspect into annotation-based aspect syntax, if you prefer that.
The console log:
execution(void de.scrum_master.stackoverflow.q75834894.app.Application.metaAnnotated())
direct
execution(void de.scrum_master.stackoverflow.q75834894.app.Application.markerAnnotated())
indirect