Java反射动态修改注解的值
先来看看通常情况下,我们通过反射获取注解的值的场景:
那么现在我们定义⼀个 @Foo 注解,它有⼀个类型为 String 的 value 属性,该注解应⽤再Field上:
/**
* @Author 落叶飞翔的蜗⽜
* @Date 2018/3/11
* @Description
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Foo {
String value();
}
再定义⼀个普通的Java对象 Bar,它有⼀个私有的String属性 value,并为它设置属性值为"test.annotation.value" 的 @Foo 注解
/**
* @Author 落叶飞翔我蜗⽜
* @Date 2018/3/11
* @Description
*/
public class Bar {
@Foo("test.annotation.value")
private String value;
}
正常的获取注解属性值的场景:
/**
* @Author 落叶飞翔的蜗⽜
* @Date 2018/3/10
* @Description
*/
@RunWith(SpringRunner.class)
public class ReflectionAnnotationTest {
@Test
public void test() throws NoSuchFieldException, IllegalAccessException {
/
/获取Bar实例
Bar bar = new Bar();
//获取Bar的val字段
Field field = Class().getDeclaredField("value");
//获取val字段上的Foo注解实例
Foo foo = Annotation(Foo.class);
//获取Foo注解实例的 value 属性值
String value = foo.value();java反射的作用及应用场景
//打印该值
System.out.println("修改之前的注解值:" + value);
}
}
我们在上⾯的String value = foo.value(); 处下断点,我们跑⼀下可以发现当前栈中有这么⼏个变量,不过其中有⼀点很特别:foo,其实是个Proxy实例。
看到foo栈中的属性h是⼀个AnnotationInvocationHandler类型的对象。h对象中包含⼀个memberValues
对象,⾥⾯装着key就是我们⾃定义注解的属性,value就是我赋的值。我们看⼀下AnnotationInvocationHandler类的源码:
class AnnotationInvocationHandler implements InvocationHandler, Serializable {
private static final long serialVersionUID = 6182022883658399397L;
private final Class<? extends Annotation> type;
private final Map<String, Object> memberValues;
可以发现memberValues对象是private final修饰的。所以我们可以通过反射修改memberValues的访问权限,来打到修改memberValues值的⽬的。
所以动态修改注解的值的⽅法为:通过反射得到foo的代理对象,然后得到代理对象的memberValues属性,修改访问权限,更新注解的value属性值。修改后的代码如下:/**
* @Author 落叶飞翔的蜗⽜
* @Date 2018/3/10
* @Description
*/
@RunWith(SpringRunner.class)
public class ReflectionAnnotationTest {
@Test
public void test() throws NoSuchFieldException, IllegalAccessException {
//获取Bar实例
Bar bar = new Bar();
//获取Bar的val字段
Field field = Class().getDeclaredField("value");
//获取val字段上的Foo注解实例
Foo foo = Annotation(Foo.class);
//获取Foo注解实例的 value 属性值
String value = foo.value();
//打印该值
System.out.println("修改之前的注解值:" + value);
System.out.println("------------以下是修改注解的值------------");
//获取 foo 这个代理实例所持有的 InvocationHandler
InvocationHandler invocationHandler = InvocationHandler(foo);
// 获取 AnnotationInvocationHandler 的 memberValues 字段
Field declaredField = Class().getDeclaredField("memberValues");
// 因为这个字段事 private final 修饰,所以要打开权限
declaredField.setAccessible(true);
// 获取 memberValues
Map memberValues = (Map) (invocationHandler);
// 修改 value 属性值
memberValues.put("value", "w.value");
// 获取 foo 的 value 属性值
String newValue = foo.value();
System.out.println("修改之后的注解值:" + newValue);
}
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论