Community
Participate
Working Groups
I have two classes, Foo and Bar @Ann class Foo { } Bar extends Foo { } I would like to have a way to match all subclasses of any class annotated with annotation @Ann. Currently I can easily match Foo, with @Ann * * *.*(..) but I cannot match Bar (unless it is explicitelly annotated with @Ann) The same could applly to methods, e.g. matching of all the methods wich override a method annotated with some annotation.
This is down to standard annotation inheritance rules for Java. By default they aren't inherited, if you mark your @Ann as being @Inherited then Bar will also have the annotation. This program demonstrates inheritance: --- import java.lang.annotation.*; @Inherited @interface Blue {} @Blue class A { } class T extends A { } aspect X { before(): staticinitialization(@Blue *) { } } --- C:\aspectj1.5.0-dev>ajc -showWeaveInfo -1.5 B.aj Type 'A' (B.aj:6) advised by before advice from 'X' (B.aj:13) Type 'T' (B.aj:9) advised by before advice from 'X' (B.aj:13) Note, inheritance *only* works for types, it will not work for methods - that is what the Java spec defines. For more discussion, see: http://eclipse.org/aspectj/doc/next/adk15notebook/annotations.html#d0e694
Yes, I'm sorry I forgot about @Inherited annotation. But as you said it works for class level annotations only, is there any way to match all methods which override some annotated method? Any AspectJ syntax?
I can't think of a way - there is no new AspectJ syntax to do it. I think its a deficiency in the java rules for @Inherited... maybe you can do something with APT to propagate the annotations down to overloaded methods, and then run AspectJ.
Yes, apt is an option but currently I avoid using it and I would prefer to. Anyways thank you for clarification.
You cannot use APT since APT does not allow to modify input artifact. You could only produce an output file or sort of, but then AspectJ weaver would ignore it. One way would be to generate an aspect with a sort of a declare annotation. Isn't there a way to write / support the following in the type pattern parser / matching mechanism: (@Ann *)+ ie all subclass(or implementation) of type annotated with @Ann so that: "within((@Ann *)+)" would solve this issue. (this at the cost of unpacking all class level annotation etc etc off course).
> You cannot use APT since APT does not allow to modify input artifact. > You could only produce an output file or sort of, but then AspectJ > weaver would ignore it. I thought APT was a source-to-source transformer? I was merely thinking a simple APT run over the code could copy annotations down from method to overridden methods completely standalone *before* AspectJ is run ?? Will that not work?? I suppose we could support (@Ann *)+ - but since @Inherited solves the problem for types...
It solves problem for types but doesn't solve problem for implemented interfaces. From @Inherited documentation: "Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class. Note also that this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect."
APT as it is now is very limited. It cannot alter its soruce. It's power comes from its cyclic behavior: if you generate a source with annotation, then this new one will be injected again as an input and so on (hence f.e. a POJO can generate an EJB 3 that can then generate a descriptor etc etc), and from its mirror API (exposes types ala java.lang.reflect somehow no matter if they come from binary dependancies or source artifact beeing build or just produced etc) But APT does not let you change the input, and neither replicate it since it does not even exposes the bodies of the methods or static{} blocks (JDT does that somehow..) Other JSR have surfaced for that - one to extract APT from the com.sun.* packages first to have it in java.* something, among other things - one to provide javac compiler extension So I guess we would need a feature request to support more complex type pattern - including in return type and parameter types. For now an if() pointcut and some reflective test can perhaps do it ?
The type pattern (@Ann *)+ matches any type with the @Ann annotation or any subtype thereof. There was a parser bug related to this pattern until recently, but that is fixed in the current development builds of AspectJ available from the download page.