Java annotations - how to get properties and class in processor

For the following custom Java annotation

@CustomAnnotation(clazz=SomeClass.class) public class MyApplicationCode { ... } 

Basically, I want to be able to capture both the class object for the MyApplicationCode parameter and the clazz parameter at compile time to confirm the consistency of coding conventions (another story). Basically, I want to have access to the MyApplicationCode.class and Someclass.class file in the annotation handler. I'm almost there, but I'm missing something. I have

 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.SOURCE) public @interface CustomAnnotation { public Class clazz(); } 

Then I have a processor:

 public class CustomAnnotationProcessor extends AbstractProcessor { private ProcessingEnvironment processingEnvironment; @Override public synchronized void init(ProcessingEnvironment processingEnvironment) { this.processingEnvironment = processingEnvironment; } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment) { Set<? extends Element> elements = environment.getElementsAnnotatedWith(ActionCommand.class); for(Element e : elements) { Annotation annotation = e.getAnnotation(CustomAnnotation.class); Class clazz = ((CustomAnnotation)annotation).clazz(); // How do I get the actual CustomAnnotation clazz? // When I try to do clazz.getName() I get the following ERROR: // Attempt to access Class object for TypeMirror SomeClass // Also, how do I get the Class object for the class that has the annotation within it? // In other words, how do I get MyApplicationCode.class? } } } 

What I'm trying to do in the process method is to grab SomeClass.class and MyApplication.class from the source code below to do some custom checking at compile time. I cannot seem that life determines me how to get these two values ​​...

 @CustomAnnotation(clazz=SomeClass.class) public class MyApplicationCode 

Update: The next post has a lot more detail, and it is much closer. But the problem is that you still have a TypeMirror object from which a class object is pulled that it does not explain: http://blog.retep.org/2009/02/13/getting-class-values-from-annotations -in-an-annotationprocessor /

Update2: You can get MyApplication.class by doing

 String classname = ((TypeElement)e).getQualifiedName().toString(); 
+4
source share
3 answers

I was about to point you towards the blog http://blog.retep.org/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/ , but it looks like you already found this.

I see that you figured out how to access the MyApplication element, so I will not cover this.

The exception you see actually contains the annotation property type in it. This way you can refer to the value of the clazz annotation when you catch the exception:

 public class CustomAnnotationProcessor extends AbstractProcessor { private ProcessingEnvironment processingEnvironment; @Override public synchronized void init(ProcessingEnvironment processingEnvironment) { this.processingEnvironment = processingEnvironment; } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment) { Set<? extends Element> elements = environment.getElementsAnnotatedWith(ActionCommand.class); for(Element e : elements) { CustomAnnotation annotation = e.getAnnotation(CustomAnnotation.class); TypeMirror clazzType = null; try { annotation.clazz(); } catch (MirroredTypeException mte) { clazzType = mte.getTypeMirror(); } System.out.println(clazzType); // should print out SomeClass } } } 

Yes, this is a complete hack of the solution, and I'm not sure why the API developers decided to go in this direction using the annotation processing function. Nevertheless, I saw how many people implement this (including myself ), and the article cited also describes this technique. This is currently an acceptable solution.

In terms of "capturing" class values ​​for MyApplicationCode and SomeClass, you cannot do this if they are compiled. However, you can use the Element and TypeMirror views to perform a high-level check on your classes (method, field, class names, annotations, etc.)

+1
source

After reading this related SO question , I found this one . This is from 2005, perhaps not the best way to do this these days.

APT [...] is an annotation processing tool for Java. More specifically, APT allows you to include code to process annotations in the source file as you compile the code β€” and in this process you can emit notes, warnings, and errors.

This is for Oracle JDK only.

0
source

This is compilation time. I think the compiler has not even finished compiling the source code. You extract such information from an AnnotatedElement instance that will give you relevant information about the type that you annotated, but not its runtime properties, which are not yet available, since the corresponding class files are not yet loaded by the virtual machine. And the compiler is not even guaranteed to work under the Java virtual machine, so class files cannot be loaded. His requirement is only to be able to create bytecodes that any particular virtual machine can read.

So, go to the Api mirror, and for any relevant information about the annotated class / method /, check out the AnnotatedElement representing this instance.

And as a side note: this information is exactly what I reasoned, so this may not be the real truth.

-1
source

Source: https://habr.com/ru/post/1413255/


All Articles