是否可以在运行时更改字段注释值?
我可以访问这些值,但无法找到更改它们的方法。
可以通过以下方式进行访问:
Article.class.declaredFields.find {it.name="annotatedField"}.declaredAnnotations
答案 0 :(得分:6)
我认为除了Field(或Object)之外,最好保持对Annotation对象的引用,并在更改其值时更新Annotation引用。这样,当Class.java中的注释实现发生变化时,您的代码就不太可能中断。
answer linked in the question comments对于处理包含单个元素的注释很有用,但如果您需要设置多个元素,则这是一个使用代理的更通用的解决方案:
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();
}
节目输出:
Old properties: old, bar, barr
New properties: new, bar, barr
New properties: new, new bar, barr