我这里有一个需求需要修改Person类中的一个属性上的注解的值进行修改,例如:
public class Person {
private int age;
@ApiParam(access="lala")
private String name;
//get set 方法忽略
}
将@ApiParam(access=“lala”) 修改为@ApiParam(access=“fafa”),经过分析是可以实现的,需要用到动态代理进行操作。
具体源码如下所示:
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiParam {
String access() default "";
}
反射+动态代理代码如下:
public class TestClazz {
public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Person person = new Person();
Field value = person.getClass().getDeclaredField("name");
value.setAccessible(true);
//APIParam 是一个自定义的注解
ApiParam apiParam = (ApiParam) value.getAnnotation(ApiParam.class);
java.lang.reflect.InvocationHandler invocationHandler = Proxy.getInvocationHandler(apiParam);
Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
//通过反射获取memberValues 这个属性是Map类型 存放着所有的属性。
memberValues.setAccessible(true);
Map<String, Object> values = (Map<String, Object>) memberValues.get(invocationHandler);
String val = (String) values.get("access");
System.out.println("------改之前:"+val);
values.put("access", "fafa");//修改属性
System.out.println("-----------------");
//Field value1 = person.getClass().getDeclaredField("name");
value.setAccessible(true);
ApiParam apiParam1 = (ApiParam) value.getAnnotation(ApiParam.class);
System.out.println("------改之后:"+apiParam1.access());
//动态代理的方式不会改变原先class文件的内容
}
}