APT How to process annotations of nested annotated classes
-
06-07-2021 - |
質問
I am trying to write an annotation processor using java. This annotation processor needs to identify annotated nested classes within an annotated class as seen below. I will process the annotated classes first then process their inner annotations. This is performed at compile time and I will have no existing knowledge of the class being processed. It is possible to have multiple nested classes within Foo. How do I process the annotations of all these nested classes.
@MyAnnotation(value="Something important")
public class Foo
{
private Integer A;
@MyMethodAnnotation(value="Something Else")
public Integer getA() { return this.A; }
@MyAnnotation(value="Something really important")
private class Bar
{
private Integer B;
@MyMethodAnnotation(value="Something Else that is very Important")
public Integer getB() { return this.B }
}
}
How can I get access to the nested Bar class, it's annotation 'MyAnnotation' and its 'MyMethodAnnotation' during processing? The following code only prints out information about class Foo. How can I process information about Bar?
for (Element element : env.getElementsAnnotatedWith(MyAnnotation.class)) {
if ( element.getKind().equals(ElementKind.CLASS) )
{
System.out.println(element.getKind().name() + " " + element.getSimpleName() );
processInnerClassElement(element);
}
else
{
System.out.println(element.getKind().name() + " " + element.getSimpleName() );
}
}
...
private void processInnerClassElement(Element element)
{
for (Element e : element.getEnclosedElements() )
{
if ( e.getKind().equals(ElementKind.CLASS) )
{
System.out.println(e.getKind().name() + " " + e.getSimpleName() );
processInnerClassElement(e);
}
else
{
System.out.println(e.getKind().name() + " " + e.getSimpleName() );
}
}
}
解決
I guess it depends how these annotation relate to each other.
You could simply declare all the annotations in @SupportedAnnotationTypes and have several blocks in the process-method like:
for (Element element : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
MyAnnotation myAnnotation = element.getAnnotation(MyAnnotation.class);
if (myAnnotation != null) {
doSomething(myAnnotation, element);
}
}
for (Element element : roundEnv.getElementsAnnotatedWith(MyMethodAnnotation.class)) {
MyMethodAnnotation myMethodAnnotation = element.getAnnotation(MyMethodAnnotation.class);
if (myMethodAnnotation != null) {
doSomething(myMethodAnnotation, element);
}
}
Otherwise you might be able to use element.getEnclosedElements()
and element.getEnclosingElement()
to achieve what you want.
他のヒント
You'll need a few methods from Class
and Method
to do this, specifically to get the classes declared in Foo
, the annotations on those classes, the methods declared in those classes, and the annotations on those methods. Here is a quick example:
public static void main(String... args) {
for (Class<?> declaredClass : Foo.class.getDeclaredClasses()) {
MyAnnotation myAnnotation = declaredClass.getAnnotation(MyAnnotation.class);
// Process value of class annotation here
for (Method method : declaredClass.getDeclaredMethods()) {
MyMethodAnnotation myMethodAnnotation = method.getAnnotation(MyMethodAnnotation.class);
// Process value of method annotation here
}
}
}
It might be insightful to read through the documentation about reflection in Java: http://docs.oracle.com/javase/tutorial/reflect/index.html