myślę, że byłoby najlepiej, aby zachować odniesienie do obiektu adnotacji oprócz swojej dziedzinie (lub obiekt) i zaktualizować odniesienie adnotacji, jak zmienić swoje wartości . W ten sposób, gdy zmienia się implementacja adnotacji w Class.java, Twój kod jest mniej podatny na złamanie.
answer linked in the question comments jest przydatna do czynienia z adnotacji zawierających pojedynczy element, ale jeśli masz kilka elementów, które trzeba ustawić, tutaj jest bardziej ogólne rozwiązanie, które sprawia, że korzystanie z serwera proxy:
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) throws Exception {
Foo foo = new Foo();
Field field = foo.getClass().getDeclaredFields()[0];
Anno anno = field.getAnnotation(Anno.class);
System.out.println(String.format("Old properties: %s, %s, %s", anno.value(), anno.bar(), anno.barr()));
Anno anno2 = (Anno) setAttrValue(anno, Anno.class, "value", "new");
System.out.println(String.format("New properties: %s, %s, %s", anno2.value(), anno2.bar(), anno2.barr()));
Anno anno3 = (Anno) setAttrValue(anno2, Anno.class, "bar", "new bar");
System.out.println(String.format("New properties: %s, %s, %s", anno3.value(), anno3.bar(), anno3.barr()));
}
public static Annotation setAttrValue(Annotation anno, Class<? extends Annotation> type, String attrName, Object newValue) throws Exception {
InvocationHandler handler = new AnnotationInvocationHandler(anno, attrName, newValue);
Annotation proxy = (Annotation) Proxy.newProxyInstance(anno.getClass().getClassLoader(), new Class[]{type}, handler);
return proxy;
}
}
class AnnotationInvocationHandler implements InvocationHandler {
private Annotation orig;
private String attrName;
private Object newValue;
public AnnotationInvocationHandler(Annotation orig, String attrName, Object newValue) throws Exception {
this.orig = orig;
this.attrName = attrName;
this.newValue = newValue;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// "override" the return value for the property we want
if (method.getName().equals(attrName) && args == null)
return newValue;
// keep other properties and methods we want like equals() and hashCode()
else {
Class<?>[] paramTypes = toClassArray(args);
return orig.getClass().getMethod(method.getName(), paramTypes).invoke(orig, args);
}
}
private static Class<?>[] toClassArray(Object[] arr) {
if (arr == null)
return null;
Class<?>[] classArr = new Class[arr.length];
for (int i=0; i<arr.length; i++)
classArr[i] = arr[i].getClass();
return classArr;
}
}
class Foo {
@Anno(value="old", bar="bar", barr="barr")
public Object field1;
}
@Retention(RetentionPolicy.RUNTIME)
@interface Anno {
String value();
String bar();
String barr();
}
Programu wyjście:
Old properties: old, bar, barr
New properties: new, bar, barr
New properties: new, new bar, barr
myślę, że odpowiedzi na swoje pytanie: http://stackoverflow.com/questions/14268981/modify-a-class-definitions-annotatio n-string-parameter-at-runtime/14276270 # 14276270 – wladimiiir
Modyfikuje adnotację klasy. Nie mogę znaleźć sposobu zastosowania jej do pola. –