5

ich Implementierung eines Annotations-Prozessor, um sicherzustellen, dass die Elemente mit einer Anmerkung markierte Instanzen einer Klasse sind, die eine bestimmte Schnittstelle implementiert, oder sind Anwendungen von Typen, die eine bestimmte Schnittstelle implementieren:Wie verarbeitet man Anmerkungen mit @Target (ElementType.TYPE_USE)?

@Documented 
@Target(value = { ElementType.PARAMETER, ElementType.TYPE_USE }) 
@Retention(value = RetentionPolicy.RUNTIME) 
public @interface AuditSubject { 

} 

public interface Auditable { 
    // methods that provide data for writing a log entry... 
} 

public class Report implements Auditable { 

} 

Für die Annotierte Elemente, ein Protokolleintrag muss nach der Methodenausführung (mit AOP) erstellt werden. Beispiele:

@CreateLogEntry 
public Result persist(@AuditSubject Report newReport) { 
    // A log entry must be created with the incoming newReport.  
} 

@CreateLogEntry 
public UpdateResult<@AuditSubject Report> update(Report update) { 
    // A log entry must be created with the updated report which is not the same instance as 'update' (cannot use it). 
} 

@CreateLogEntry 
public Result persistBatch(List<@AuditSubject Report> batch) { 
    // A log entry must be created for each element in 'batch' after this method execution. 
} 

Die Protokolleinträge müssen erstellt werden, vorausgesetzt, Report implementiert Auditable; Wenn nicht, wird eine Laufzeitausnahme ausgelöst (Huch, ich habe vergessen, die Schnittstelle zu implementieren!). Somit hilft der Annotationsprozessor, Programmiererfehler zur Kompilierzeit zu erfassen. Bis jetzt war es mir gelungen, alle Verwendungen in Parametern zu überprüfen, aber nicht in Typverwendungen. Der entsprechende Code aus dem Annotation-Prozessor ist wie folgt:

@Override 
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 
    for (Element annotated : roundEnv.getElementsAnnotatedWith(AuditSubject.class)) { 
     // Only prints elements with ElementKind.PARAMETER)! 
     this.messager.printMessage(Kind.NOTE, TextUtils.replaceParams("annotated: {} ; Kind : {} ; enclosing : {}", annotated, annotated.getKind(), annotated.getEnclosingElement())); 

     if (annotated.getKind() == ElementKind.PARAMETER) { 
      // Code here works as expected, raises errors for annotated parameters of classes that don't implement Auditable. 
     } else if (annotated.getKind() == ElementKind.WHAT_TO_USE) { 
      // What ElementKind do I need to use here? 
     } 
    } 

    return false; 
} 

Nur kommentierte Elemente mit Art ElementKind.PARAMETER erkannt werden (die erste Zeile in der Schleife des Prozesses() druckt nur eine einzige Zeile für 'newReport') Wie kann ich überprüfen, ob die kommentierten Typen implementieren Audible? Es gibt keine "ElementKind.TYPE_USE" Konstante zu verwenden. Ich konnte keine relevanten Informationen zu diesem Thema finden. Danke für Ihre Aufmerksamkeit.

Antwort

4

Die API für Java-Annotationsverarbeitung wurde entwickelt, wenn Java nur Anmerkungen zu Deklarationen unterstützt. Die API unterstützt nur Besuchserklärungen wie Felder, Methoden und Methodenparameter. Es werden weder lokale Variablendeklarationen noch andere Anmerkungen in einem Methodenkörper aufgerufen, noch werden Anmerkungen eingegeben.

Wenn Sie Typanmerkungen oder Anmerkungen in Methodenkörpern verarbeiten möchten, müssen Sie Ihren eigenen Code schreiben, um auf Typen zu rekursieren oder die Codezeilen innerhalb einer Methode erneut zu untersuchen.

Eine Alternative dazu ist ein Werkzeug wie das Checker Framework zu verwenden. Es implementiert seine eigenen Besucher und daher wird ein Annotationsprozessor, der darauf aufgebaut ist, für jedes Auftreten einer Typannotation aufgerufen.

Verwandte Themen