This question might be a little esoteric, but still I am wondering how to solve
the following problem without using reflection:
Lately I discovered that I can express "classes annotated by some annotation
which in turn is annotated by another annotation Y" like this:
within(@(@Y *) *)
Here is a little example:
-------------------------------------------------
package de.scrum_master.app;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface OuterAnnotation {}
-------------------------------------------------
package de.scrum_master.app;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@OuterAnnotation
public @interface InnerAnnotation {}
-------------------------------------------------
package de.scrum_master.app;
import java.lang.annotation.Annotation;
@InnerAnnotation
public class Application {
public static void main(String[] args) {
for (Annotation annotation : Application.class.getAnnotations())
System.out.println(annotation);
}
}
-------------------------------------------------
Console log:
@de.scrum_master.app.InnerAnnotation()
-------------------------------------------------
Of course, the annotations on interfaces are never inherited or accumulated in
any way by the JVM, so it is no surprise that Application has @InnerAnnotation,
but not @OuterAnnotation. So far, so good.
But still I am able to say to AspectJ: Give me classes annotated by some
annotation X which itself is annotated by @OuterAnnotation:
-------------------------------------------------
package de.scrum_master.aspect;
import de.scrum_master.app.OuterAnnotation;
public aspect MetaAnnotationAspect {
after() : within(@(@OuterAnnotation *) *) && execution(* *(..)) {
System.out.println("@OuterAnnotation -> " + thisJoinPoint);
}
}
-------------------------------------------------
Console log:
@de.scrum_master.app.InnerAnnotation()
@OuterAnnotation -> execution(void
de.scrum_master.app.Application.main(String[]))
Besides, this is not just a theoretical example. In Spring you could e.g. want
to capture all methods which are somehow connected with @RequestMapping. But
obviously current Spring versions use this annotation indirectly by decorating
annotations such as by @GetMapping, @PostMapping by @RequestMapping. Here the
syntax mentioned above comes in handy because now you can have a method like
@GetMapping public void blah()
and capture it like this:
after() : execution(@(@RequestMapping *) * *(..)) {
System.out.println(thisJoinPoint);
}
This is really useful and it even works recursively. This gets all methods
annotated by an annotation @X annotated by another annotation @Y annotated by
@Target:
after() : within(@(@(@Target *) *) *) && execution(* *(..)) {
System.out.println(thisJoinPoint);
}
Now here is the actual question: Is there any way other than by reflection that
I can bin the inner(most) annotation or any other annotation in the chain to
pointcut arguments via @annotation(), @args() or whatever syntactic means so as
to be able to inspect its properties? E.g. I could inspect which target types
the @Target annotation in the above example has in its ElementType[]. I tried
several syntax variations which might have done what I hoped for, such as
trying to use (nested) versions of @within() or within(), but other than syntax
errors the closest I could get to solving the problem was producing AspectJ
compiler error dumps, giving me a slight hope that it might somehow work and
just a compiler bug would be in the way.
So much for my (maybe not so) esoteric problem. I do not need it for production
today, it is just a nifty little exercise, but I might use it tomorrow or next
year if I know that it actually works.
Regards
--
Alexander Kriegisch
https://scrum-master.de
_______________________________________________
aspectj-users mailing list
[email protected]
To change your delivery options, retrieve your password, or unsubscribe from
this list, visit
https://dev.eclipse.org/mailman/listinfo/aspectj-users