java annotations annotation-processing java-compiler-api

java - Procesador de anotaciones: cómo obtener la clase que está procesando



annotations annotation-processing (2)

No puede acceder a la clase que está procesando el procesador de anotaciones porque la clase aún no se ha compilado. En cambio, Java ofrece la api de Elementos análogos para la inspección del estilo de reflexión de la fuente de entrada.

El elemento (que encontraste al usar roundEnv.getRootElements() ) tiene mucha más información sobre la clase que se está compilando que solo su nombre. Se puede encontrar una tonelada de información útil usando ElementVisitors:

http://docs.oracle.com/javase/6/docs/api/javax/lang/model/element/ElementVisitor.html http://docs.oracle.com/javase/6/docs/api/javax/lang /model/util/ElementKindVisitor6.html

Incluyendo el constructor de clases, métodos, campos, etc.

He aquí cómo usarlo:

public class AnnotationProcessor extends AbstractProcessor { ...... @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { Set<? extends Element> rootE=roundEnv.getRootElements(); for(Element e: rootE) { for(Element subElement : e.getEnclosedElements()){ subElement.accept(new ExampleVisitor(), null); // implement ExampleVisitor } } } }

Estoy tratando de escribir un procesador de Anntoation personalizado. El procesador de anotaciones procesará cada archivo de clase en tiempo de compilación para comprobar las anotaciones. ¿Pero cómo puedo obtener la clase que está procesando actualmente? Solo puedo obtener el nombre de la clase en los siguientes códigos.

public class AnnotationProcessor extends AbstractProcessor { ...... @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { Set<? extends Element> rootE=roundEnv.getRootElements(); for(Element e: rootE) { if(e.getKind()==ElementKind.CLASS) { String className= e.getSimpleName().toString(); processingEnv.getMessager().printMessage( javax.tools.Diagnostic.Kind.WARNING,className, e); } } }


  1. NO es así como funciona AnnotationProcessing. ¡No puede obtener un objeto Class<?> Durante el procesamiento porque las clases de las que quiere una definición se están compilando AHORA MISMO ! Si llama a getClass() en una clase desconocida o usa Class<?> clazz = Class.forName("com.your.fancy.Class") , obtendrá java.lang.ClassNotFoundException que está completamente Class<?> clazz = Class.forName("com.your.fancy.Class") .
  2. Necesita usar clases como javax.lang.model.element.Element y javax.lang.model.element.ExecutableElement para describir / leer sus definiciones de clase.
  3. javax.lang.model.* Tiene javax.lang.model.type.TypeMirror para describir clases, sus campos, métodos, etc.
  4. Si necesita más información, simplemente incluya tools.jar del compilador de java (JAVA SDK) para obtener más definiciones de tipo que se utilizan durante la compilación. Pero lo más probable es que NO necesite agregar esta dependencia de jar.
  5. Obtendrá ClassNotFoundException incluso después de roundEnvironment.processingOver() es verdadero .
  6. EN CORTO: USE TypeMirror en todos los lugares donde quería usar el tipo Class .

Ejemplos:

  • obtener una lista de métodos de una clase:

public static @Nonnull List getMethods(@Nonnull Element annotationElem, @Nonnull RoundEnvironment roundEnvironment) { List outList = new ArrayList(); String simpleName = annotationElem.getSimpleName().toString(); for (Element elem : roundEnvironment.getRootElements()) if (elem.getSimpleName().toString().equals(simpleName)) for (Element methodDeclaration :elem.getEnclosedElements()) if (methodDeclaration instanceof ExecutableElement) outList.add((ExecutableElement)methodDeclaration); return outList; }

  • obtener el nombre del método de la declaración del método:

public static TypeMirror getMethodFirstParam(@Nonnull ExecutableElement method, int n) { List parameters = ((ExecutableElement) method).getParameters(); if (parameters != null && parameters.size() > 0) return parameters.get(n).asType(); return null; }