Ändern der Anmerkungsparameter zur Laufzeit

Anmerkungsparameter zur Laufzeit ändern

1. Überblick

Annotations, eine Form von Metadaten, die Sie zum Java-Code hinzufügen können. Dieseannotations -Scans werden zur Kompilierungszeit verarbeitet und in Klassendateien eingebettet oder können zur Laufzeit mitReflection beibehalten und aufgerufen werden.

In diesem Artikel wird erläutert, wie Sie den Wert vonannotationzur Laufzeit mithilfe vonReflection ändern. In diesem Beispiel wird eine Annotation auf Klassenebene verwendet.

2. Anmerkung

Java ermöglicht das Erstellen neuerannotationsmit vorhandenen. In der einfachsten Form wird eine Annotation als@-Symbol dargestellt, gefolgt vom Annotationsnamen:

@Override

Erstellen wir unsere eigene AnnotationGreeter:

@Retention(RetentionPolicy.RUNTIME)
public @interface Greeter {
    public String greet() default "";
}

Jetzt erstellen wir eine Java-KlasseGreetings, die die Klassenstufeannotation: verwendet

@Greeter(greet="Good morning")
public class Greetings {}

Jetzt greifen wir mit Reflection auf den Annotation-Wert zu. Die Java-KlasseClass bietet eine MethodegetAnnotation für den Zugriff auf Anmerkungen einer Klasse:

Greeter greetings = Greetings.class.getAnnotation(Greeter.class);
System.out.println("Hello there, " + greetings.greet() + " !!");

3. Anmerkung ändern

Die Java-KlasseClass verwaltet eine Karte zum Verwalten von Anmerkungen -Annotation Klasse als Schlüssel undAnnotation Objekt als Wert:

Map, Annotation> map;

Wir werden diese Map aktualisieren, um die Annotation zur Laufzeit zu ändern. Die Vorgehensweise für den Zugriff auf diese Zuordnung unterscheidet sich in verschiedenen JDK-Implementierungen. Wir werden es für JDK7 und JDK8 diskutieren.

3.1. JDK 7-Implementierung

Die Java-KlasseClass hat das Feldannotations. Da dies ein privates Feld ist, müssen wir die Zugänglichkeit des Feldes auftrue setzen, um darauf zugreifen zu können. Java bietet die MethodegetDeclaredField , um auf jedes Feld mit seinem Namen zuzugreifen:

Field annotations = Class.class.getDeclaredField(ANNOTATIONS);
annotations.setAccessible(true);

Lassen Sie uns nun auf die Anmerkungszuordnung für KlasseGreeterzugreifen:

 Map, Annotation> map = annotations.get(targetClass);

Dies ist nun die Map, die Informationen zu allen Annotationen und deren Wertobjekten enthält. Wir möchten den Anmerkungswert vonGreeterändern, den wir durch Aktualisieren des Anmerkungsobjekts der KlasseGreetererreichen können:

map.put(targetAnnotation, targetValue);

3.2. JDK 8-Implementierung

Java 8-Implementierungen speichern die Informationen vonannotationsinnerhalb einer KlasseAnnotationData. Wir können mit der MethodeannotationDataauf dieses Objekt zugreifen. Wir werden die Zugänglichkeit für dieannotationData-Methode auftrue setzen, da es sich um eine private Methode handelt:

Method method = Class.class.getDeclaredMethod(ANNOTATION_METHOD, null);
method.setAccessible(true);

Jetzt können wir auf das Feldannotationszugreifen. Da dieses Feld auch ein privates Feld ist, setzen wir die Zugänglichkeit auftrue:

Field annotations = annotationData.getClass().getDeclaredField(ANNOTATIONS);
annotations.setAccessible(true);

Dieses Feld enthält eine Anmerkungs-Cache-Zuordnung, in der die Anmerkungsklasse und das Wertobjekt gespeichert sind. Ändern wir das:

Map, Annotation> map = annotations.get(annotationData);
map.put(targetAnnotation, targetValue);

4. Anwendung

Nehmen wir dieses Beispiel:

Greeter greetings = Greetings.class.getAnnotation(Greeter.class);
System.err.println("Hello there, " + greetings.greet() + " !!");

Dies wird "Guten Morgen" heißen, da dies der Wert ist, den wir für die Annotation angegeben haben. Jetzt erstellen wir ein weiteres Objekt vom TypGreetermit dem Wert "Guten Abend":

Greeter targetValue = new DynamicGreeter("Good evening");

Aktualisieren wir die Anmerkungskarte mit dem neuen Wert:

alterAnnotationValueJDK8(Greetings.class, Greeter.class, targetValue);

Überprüfen wir den Begrüßungswert erneut:

greetings = Greetings.class.getAnnotation(Greeter.class);
System.err.println("Hello there, " + greetings.greet() + " !!");

Es wird als "Guten Abend" begrüßen.

5. Fazit

Java-Implementierungen verwenden zwei Datenfelder zum Speichern von Anmerkungsdaten:annotations,declaredAnnotations. Der Unterschied zwischen diesen beiden: Speichern Sie zuerst auch Anmerkungen aus übergeordneten Klassen, und speichern Sie später nur für die aktuelle Klasse.

Da sich die Implementierung vongetAnnotation in JDK 7 und JDK 8 unterscheidet, verwenden wir hier der Einfachheit halber die Feldkarteannotations .

Und wie immer ist der Quellcode der Implementierungover on Github verfügbar.