Werte einer Java 5 Annotation zur Laufzeit ändern.

Thomas Darimont

Erfahrenes Mitglied
Hallo!

here is another funny hack :)
Java:
package de.tutorials.training;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
 
public class AnnotationValueChangeExample {
 
    public static void main(String[] args) {
        Foo foo = new Foo();
        
        System.out.println(foo.getClass().isAnnotationPresent(SomeAnnotation.class));
        
        SomeAnnotation someAnnotation = foo.getClass().getAnnotation(SomeAnnotation.class);
        System.out.println(someAnnotation);
        changeValuesOfAnnotation(someAnnotation, new HashMap<String, String>(){{put("value", "Test2");}});
        System.out.println(foo.getClass().getAnnotation(SomeAnnotation.class));
    }
 
    private static void changeValuesOfAnnotation(
            Object someAnnotation,
            Map<String, String> newValues) {
        if (Proxy.isProxyClass(someAnnotation.getClass())) {
            Object invocationHandler = Proxy.getInvocationHandler(someAnnotation);
            try {
                Field field = invocationHandler.getClass().getDeclaredField("memberValues");
                field.setAccessible(true);
                field.set(invocationHandler, newValues);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
 
    @SomeAnnotation("Test")
    static class Foo {
    }
 
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    static @interface SomeAnnotation {
        String value();
    }
 
}

Ausgabe:
Code:
true
@de.tutorials.training.AnnotationValueChangeExample$SomeAnnotation(value=Test)
@de.tutorials.training.AnnotationValueChangeExample$SomeAnnotation(value=Test2)

Gruß Tom
 
Der Beitrag ist etwas älter, aber dennoch excellent :)

Nachdem die Manipulation von Klassen Annotationen damit wunderbar bedient wird.
Frage ich mich wie das ganze für Methoden aussieht.

Klasse Foo mit annotierter Methode:
Code:
    @SomeAnnotation("Test")
    static class Foo {
          @AnnotherAnnotation(value = "test.csv")
          public void method(){};
    }

Annotation für die Methode:
Code:
     @Retention(RetentionPolicy.RUNTIME)
    static @interface AnnotherAnnotation{
        String value();
    }

Test:
Code:
    public void overrideAnnotation() {
        //set annotation
        for (Method m : this.getClass().getDeclaredMethods()) {
            if (m.isAnnotationPresent(AnotherAnnotation.class)) {
                Annotation annotation = m.getAnnotation(AnotherAnnotation.class);
                System.out.println(annotation);
                Map<String,Object> newValues = new LinkedHashMap<String,Object>();
                newValues.put("value", "new.csv");
                ModifyAnnotationValues.changeValueOfAnnotation(annotation, newValues);
                System.out.println(annotation);
            }
        }
        // re-read annotation value
        for (Method m : this.getClass().getDeclaredMethods()) {
            if (m.isAnnotationPresent(AnotherAnnotation.class)) {
                Annotation annotation = m.getAnnotation(myAnnotation.class);
                System.out.println(annotation);
            }
        }
    }

Output:
Code:
@package.AnotherAnnotation(value=test.csv)         // Wert der Annotattion vor set 
@package.AnotherAnnotation(value=new.csv)        // Wert der Annotation nach set
@package.AnotherAnnotation(value=test.csv)        // Wert der Annotation nach wiederholtem einlesen

Kann mir jmd sagen, warum das setzen der Annotions-Werte bei einer Klasse funktioniert, aber bei einer annotierten Methode nicht?

Gruß,
kopfpilot
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück