修改字段注释值动态 [英] Modify field annotation value dynamically

查看:424
本文介绍了修改字段注释值动态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

时,可以在运行时改变字段批注值?

我可以访问值,但不能找到一种方法来改变他们。

访问是可能的:

  Article.class.declaredFields.find {it.name =annotatedField}。declaredAnnotations


解决方案

我认为这将是最好保持在除了你的场(或对象)Annotation对象的引用,当您更改更新注释引用其值。这样,当在Class.java改变注释的执行,你的code是不太可能打破。

的<一个href=\"http://stackoverflow.com/questions/14268981/modify-a-class-definitions-annotation-string-parameter-at-runtime\">answer在这个问题评论是处理含有单个元素的注解有用的链接,但如果你有,你需要设置多个元素,这里是一个更普遍的解决方案,使使用代理的:

 进口java.lang.annotation.Annotation;
进口java.lang.annotation.Retention;
进口java.lang.annotation.RetentionPolicy;
进口java.lang.reflect.Field中;
进口java.lang.reflect.InvocationHandler;
进口的java.lang.reflect.Method;
进口java.lang.reflect.Proxy;公共类的测试{
    公共静态无效的主要(字串[] args)抛出异常{
        富富=新的Foo();
        场场= foo.getClass()getDeclaredFields()[0]。        安诺安诺= field.getAnnotation(Anno.class);
        的System.out.println(的String.format(老属性:%S%S%S,anno.value(),anno.bar(),anno.barr()));        安诺anno2 =(安诺)setAttrValue(阿鲁,Anno.class,价值,新);
        的System.out.println(的String.format(新属性:%S%S%S,anno2.value(),anno2.bar(),anno2.barr()));        安诺anno3 =(安诺)setAttrValue(anno2,Anno.class,酒吧,新巴);
        的System.out.println(的String.format(新属性:%S%S%S,anno3.value(),anno3.bar(),anno3.barr()));
    }    公共静态诠释setAttrValue(译注阿鲁,班&LT ;?扩展注解&GT;类型,字符串attrName,对象为newValue)抛出异常{
        InvocationHandler的处理程序=新AnnotationInvocationHandler(阿鲁,attrName,为newValue);
        注释代理=(译注)Proxy.newProxyInstance(anno.getClass()getClassLoader(),新的Class [] {}类型,处理程序);
        返回代理;
    }
}类AnnotationInvocationHandler实现的InvocationHandler {
    私人注释原稿;
    私有String attrName;
    私有对象为newValue;    公共AnnotationInvocationHandler(译注原稿,弦乐attrName,对象为newValue)抛出异常{
        this.orig =原稿;
        this.attrName = attrName;
        this.newValue =为newValue;
    }    @覆盖
    公共对象的invoke(对象代理,方法的方法,对象[]参数)抛出的Throwable
        //覆盖我们想要的属性的返回值
        如果(method.getName()等于(attrName)及&安培; ARGS == NULL)
            返回为newValue;        //保持其他属性和方法,我们要像equals()和哈希code()
        其他{
            类&LT;&GT; [] paramTypes = toClassArray(参数);
            返回orig.getClass()实现getMethod(method.getName(),paramTypes).invoke(原稿,参数)。
        }
    }    私有静态类&LT;&GT; [] toClassArray(对象[] ARR){
        如果(ARR == NULL)
            返回null;
        类&LT;&GT; [] = classArr新的Class [arr.length]
        的for(int i = 0; I&LT; arr.length;我++)
            classArr [I] =改编[I] .getClass();
        返回classArr;
    }}类Foo {
    @Anno(值=老,酒吧=酒吧,巴尔=巴尔)
    公共对象字段1;
}@Retention(RetentionPolicy.RUNTIME)
@interface安诺{
    字符串值();
    弦杆();
    串巴尔();
}

程序输出:

 老属性:老,酒吧,巴尔
新特性:新的吧,巴尔
新特性:全新的,新开的酒吧,巴尔

Is is possible to change field annotation values at runtime?

I can access the values, but can't find a way to change them.

Access is possible with:

Article.class.declaredFields.find {it.name="annotatedField"}.declaredAnnotations

解决方案

I think it would be best to keep a reference to an Annotation object in addition to your Field (or Object), and update the Annotation reference as you change its values. This way, when the implementation of annotations in Class.java changes, your code is less likely to break.

The answer linked in the question comments is useful for dealing with annotations containing a single element, but if you have multiple elements that you need to set, here is a more general solution that makes use of a 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();
}

Program output:

Old properties: old, bar, barr
New properties: new, bar, barr
New properties: new, new bar, barr

这篇关于修改字段注释值动态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆