我有一个简单的注释,用于在运行时编辑地图的键:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface UpdateKey
{
String oldKey() default ""; //The key that needs to be replaced
String newKey() default ""; //The new key
}
而且我正在某类的方法上使用它:
public class CustomMap
{
@UpdateKey(oldKey = "description", newKey = "productName")
public void editMap(Map<String,String> map) throws NoSuchMethodException
{
//get the annotation values
UpdateKey updateKey = this.getClass().getMethod("editMap").getAnnotation(UpdateKey.class);
//save value and delete old key
Object obj = map.remove(updateKey.oldKey());
//set the value to the new key
map.put(updateKey.newKey(),obj);
}
}
但是在调用该方法之前,似乎没有任何操作可操作此注释,我已经尝试过:
// get the edit map method
Method method = CustomMap.class.getDeclaredMethod("editMap");
// get the annotation
UpdateKey updateKeyAnnotation = method.getDeclaredAnnotation(UpdateKey.class);
Object handler = Proxy.getInvocationHandler(updateKeyAnnotation);
//this is retrieving the reflection class fields NOT my annotation fields
sout(handler.getClass().getDeclaredFields());
Field f;
//of course this will fail since there is no oldKey field in the reflection class
f = handler.getClass().getDeclaredField("oldKey");
伙计,您距离解决方案仅2步之遥。检索调用处理程序后,必须更改它的字段memberValues。这是完整的代码:
import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class NewApp {
public static void main(String[] args) throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException {
// get the edit map method
Method method = CustomMap.class.getDeclaredMethod("editMap", Map.class);
// get the annotation
UpdateKey updateKeyAnnotation = method.getDeclaredAnnotation(UpdateKey.class);
System.out.println("current annotation: " + updateKeyAnnotation);
Object handler = Proxy.getInvocationHandler(updateKeyAnnotation);
System.out.println(Arrays.toString(handler.getClass().getDeclaredFields()));
// field memberValues contains annotation attributes and their values
// just modify it
Field memberValues = handler.getClass().getDeclaredField("memberValues");
memberValues.setAccessible(true);
System.out.println(memberValues.get(handler));
Map<String, String> annotationAttributes = new HashMap<>();
annotationAttributes.put("newKey", "otherProduct");
annotationAttributes.put("oldKey", "otherDescription");
memberValues.set(handler, annotationAttributes);
System.out.println("changed annotation: " + updateKeyAnnotation);
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface UpdateKey {
String oldKey() default ""; //The key that needs to be replaced
String newKey() default ""; //The new key
}
class CustomMap {
@UpdateKey(oldKey = "description", newKey = "productName")
public void editMap(Map<String, String> map) throws NoSuchMethodException {
//get the annotation values
UpdateKey updateKey = this.getClass().getMethod("editMap").getAnnotation(UpdateKey.class);
//save value and delete old key
Object obj = map.remove(updateKey.oldKey());
//set the value to the new key
map.put(updateKey.newKey(), obj.toString());
}
}
此代码的输出
current annotation: @UpdateKey(newKey=productName, oldKey=description)
[private static final long sun.reflect.annotation.AnnotationInvocationHandler.serialVersionUID, private final java.lang.Class sun.reflect.annotation.AnnotationInvocationHandler.type, private final java.util.Map sun.reflect.annotation.AnnotationInvocationHandler.memberValues, private transient volatile java.lang.reflect.Method[] sun.reflect.annotation.AnnotationInvocationHandler.memberMethods, static final boolean sun.reflect.annotation.AnnotationInvocationHandler.$assertionsDisabled]
{newKey=productName, oldKey=description}
changed annotation: @UpdateKey(oldKey=otherDescription, newKey=otherProduct)