动态修改注解上的参数
最近有一个需求,需要用自定义注解覆盖原来的注解进行入参,不过水平有限,一时间没有想到什么好办法(希望大家能给点建议 谢谢啦)
最后只能用一个本办法,在运行时对注解参数进行一个动态的修改。
感谢百度到的大佬们的资料,在了解了一些注解相关的知识后,终于实现了参数的修改
- Java 虚拟机使用的“真实”注释类的实例是动态代理的实例。
- Java 注解有一个名为
memberValues
的私有Map,其中存储了属性名称和属性值的k-v
对。
综合以上信息得出,可以通过反射来访问实例,然后用给定的新值替换现有值,从而实现动态修改注解参数。
-
Proxy JDK 动态代理对象
可通过其
getInvocationHandler
方法获取注解的代理实例 -
InvocationHandler 调用处理器
每一个被代理的实例都有一个调用处理器,通过反射获取被代理类的实例的属性值
package com.yinhai.apidemo;
import com.yinhai.apidemo.anno.DIY;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.Map;
/**
* @Author Chujiao
* @Date 2019/9/17 13:51
* @Version 1.0
*/
@DIY("友情破颜拳")
public class ChangeParamTest {
public static void main(String[] args) {
// 获取到DIY注解
DIY diy = ChangeParamTest.class.getAnnotation(DIY.class);
System.out.println("注解原本的参数: "+diy.value());
// 获取到代理处理器
Object handler = Proxy.getInvocationHandler(diy);
Field f;
try {
// 获取 memberValues
f = handler.getClass().getDeclaredField("memberValues");
} catch (NoSuchFieldException | SecurityException e) {
throw new IllegalStateException(e);
}
f.setAccessible(true);
Map<String, Object> memberValues;
try {
// 获取memberValues的map实例
memberValues = (Map<String, Object>) f.get(handler);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
// 修改需要的值
memberValues.put("value","星爆气流斩");
System.out.println("注解替换后的参数: "+diy.value());
}
}
运行结果:
注解原本的参数: 友情破颜拳
注解替换后的参数: 星爆气流斩
Process finished with exit code 0
可以看到注解中的值已经成功替换了,不过总觉得这样做太过麻烦了,这种方法更多还是适用于旧项目改造,或者是无法操作源码的情况。对于我这种只是想修改下注解的属性和填入参数的方式的情况,希望大佬们能给点提议。目前这种方式虽然也可以做到,而且确实减少了很多的重复工作量,但是总觉得应该还有更简单的办法
留个记录,希望以后自己能解答自己的问题