5

Ich versuche, einen benutzerdefinierten Anntation Prozessor zu schreiben. Der Annotationsprozessor verarbeitet jede Klassendatei zur Kompilierzeit, um die Annotationen zu überprüfen, Aber wie kann ich die Klasse bekommen, die sie gerade bearbeitet? Ich bin nur in der Lage, den Klassennamen in den folgenden Codes zu erhalten.Annotation Processor - Wie bekomme ich die Klasse, die es verarbeitet

Antwort

7

Sie können nicht auf die Klasse zugreifen, die der Annotationsprozessor verarbeitet, da die Klasse noch nicht kompiliert wurde. Stattdessen bietet Java die analoge Elements-API für die Reflexionsprüfung der Eingangsquelle an.

Das Element (das Sie mit roundEnv.getRootElements() gefunden haben) enthält viel mehr Informationen über die kompilierte Klasse als nur ihren Namen.

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

Einschließlich der Klassen Konstruktor, Methoden, Felder etc.

Hier ist, wie es zu benutzen: Eine Tonne nützliche Informationen können unter Verwendung der ElementVisitors finden

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 
      } 
     } 
    } 
} 
+0

Danke für Ihre Hilfe: D – user1004413

+0

Sie sagen "... hat viel mehr Informationen über die kompilierte Klasse als nur ihren Namen", aber wie _do_ erhalten Sie den Klassennamen? – Matthias

+0

Der Klassenname wird in der Element.getSimpleName() http://docs.oracle.com/javase/7/docs/api/javax/lang/model/element/Element.html#getSimpleName%28%29 –

3
  1. ist nicht wie AnnotationProcessing funktioniert. Sie können kein Class<?> Objekt während der Verarbeitung erhalten, da die Klassen, die Sie definieren möchten, gerade jetzt kompiliert werden! Wenn Sie getClass() in einer unbekannten Klasse anrufen oder Class<?> clazz = Class.forName("com.your.fancy.Class") verwenden, erhalten Sie java.lang.ClassNotFoundException, was völlig in Ordnung ist.
  2. Sie müssen Klassen wie javax.lang.model.element.Element und javax.lang.model.element.ExecutableElement verwenden, um Ihre Klassendefinitionen zu beschreiben/zu lesen.
  3. Die javax.lang.model.* hat javax.lang.model.type.TypeMirror Klassen zu beschreiben, ihre Felder, Methoden usw.
  4. Wenn Sie mehr Einblick benötigen, nur tools.jar vom Java-Compiler (JAVA SDK) enthalten, um mehr Typdefinitionen zu erhalten, die Wird während der Kompilierung verwendet. Aber höchstwahrscheinlich - Sie brauchen nicht, um diese Glasabhängigkeit hinzuzufügen!
  5. Sie erhalten ClassNotFoundException auch nach roundEnvironment.processingOver() ist True.
  6. KURZ: Verwenden Sie TypeMirror an allen Stellen, an denen Sie den Klassentyp verwenden möchten.

Beispiele:

  • get Liste von Methoden aus einer Klasse:
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; 
}
  • get-Methode Namen von Methodendeklaration:
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; 
}
+0

ist der annotationElem ein Wurzelelement der roundEnvironment? – Sunnyday

Verwandte Themen