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);
}
}
}
- 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 agetClass()
en una clase desconocida o usaClass<?> clazz = Class.forName("com.your.fancy.Class")
, obtendrájava.lang.ClassNotFoundException
que está completamenteClass<?> clazz = Class.forName("com.your.fancy.Class")
. - Necesita usar clases como
javax.lang.model.element.Element
yjavax.lang.model.element.ExecutableElement
para describir / leer sus definiciones de clase. -
javax.lang.model.*
Tienejavax.lang.model.type.TypeMirror
para describir clases, sus campos, métodos, etc. - 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.
- Obtendrá
ClassNotFoundException
incluso después deroundEnvironment.processingOver()
es verdadero . - 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;
}