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
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
}
}
}
}
- 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 SiegetClass()
in einer unbekannten Klasse anrufen oderClass<?> clazz = Class.forName("com.your.fancy.Class")
verwenden, erhalten Siejava.lang.ClassNotFoundException
, was völlig in Ordnung ist. - Sie müssen Klassen wie
javax.lang.model.element.Element
undjavax.lang.model.element.ExecutableElement
verwenden, um Ihre Klassendefinitionen zu beschreiben/zu lesen. - Die
javax.lang.model.*
hatjavax.lang.model.type.TypeMirror
Klassen zu beschreiben, ihre Felder, Methoden usw. - 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!
- Sie erhalten
ClassNotFoundException
auch nachroundEnvironment.processingOver()
ist True. - 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;
}
ist der annotationElem ein Wurzelelement der roundEnvironment? – Sunnyday
Danke für Ihre Hilfe: D – user1004413
Sie sagen "... hat viel mehr Informationen über die kompilierte Klasse als nur ihren Namen", aber wie _do_ erhalten Sie den Klassennamen? – Matthias
Der Klassenname wird in der Element.getSimpleName() http://docs.oracle.com/javase/7/docs/api/javax/lang/model/element/Element.html#getSimpleName%28%29 –