在运行时修改类定义的注释字符串参数想象一下有一个类:@Something(someProperty = "some value")public class Foobar {
//...}它已经编译(我无法控制源代码),并且是JVM启动时类路径的一部分。我希望能够在运行时将“某些值”更改为其他值,这样以后的任何反射都将使我的新价值而不是默认的“一些值”。这个是可能的吗?如果是,怎么做?
3 回答
倚天杖
TA贡献1828条经验 获得超3个赞
/** * Changes the annotation value for the given key of the given annotation to newValue and returns * the previous value. */@SuppressWarnings("unchecked")public static Object changeAnnotationValue(Annotation annotation, String key, Object newValue){ Object handler = Proxy.getInvocationHandler(annotation); Field f; try { f = handler.getClass().getDeclaredField("memberValues"); } catch (NoSuchFieldException | SecurityException e) { throw new IllegalStateException(e); } f.setAccessible(true); Map<String, Object> memberValues; try { memberValues = (Map<String, Object>) f.get(handler); } catch (IllegalArgumentException | IllegalAccessException e) { throw new IllegalStateException(e); } Object oldValue = memberValues.get(key); if (oldValue == null || oldValue.getClass() != newValue.getClass()) { throw new IllegalArgumentException(); } memberValues.put(key,newValue); return oldValue;}
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface ClassAnnotation { String value() default "";}@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface FieldAnnotation { String value() default "";}@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface MethodAnnotation { String value() default "";}@ClassAnnotation("class test")public static class TestClass{ @FieldAnnotation("field test") public Object field; @MethodAnnotation("method test") public void method(){ }}public static void main(String[] args) throws Exception { final ClassAnnotation classAnnotation = TestClass.class.getAnnotation(ClassAnnotation.class); System.out.println("old ClassAnnotation = " + classAnnotation.value()); changeAnnotationValue(classAnnotation, "value", "another class annotation value"); System.out.println("modified ClassAnnotation = " + classAnnotation.value()); Field field = TestClass.class.getField("field"); final FieldAnnotation fieldAnnotation = field.getAnnotation(FieldAnnotation.class); System.out.println("old FieldAnnotation = " + fieldAnnotation.value()); changeAnnotationValue(fieldAnnotation, "value", "another field annotation value"); System.out.println("modified FieldAnnotation = " + fieldAnnotation.value()); Method method = TestClass.class.getMethod("method"); final MethodAnnotation methodAnnotation = method.getAnnotation(MethodAnnotation.class); System.out.println("old MethodAnnotation = " + methodAnnotation.value()); changeAnnotationValue(methodAnnotation, "value", "another method annotation value"); System.out.println("modified MethodAnnotation = " + methodAnnotation.value());}
哔哔one
TA贡献1854条经验 获得超8个赞
ignoreUnknown
@JsonIgnoreProperties(ignoreUnknown = true)
final List<Annotation> matchedAnnotation = Arrays.stream(SomeClass.class.getAnnotations()).filter(annotation -> annotation.annotationType(). equals(JsonIgnoreProperties.class)).collect(Collectors.toList()); final Annotation modifiedAnnotation = new JsonIgnoreProperties() { @Override public Class<? extends Annotation> annotationType() { return matchedAnnotation.get(0).annotationType(); } @Override public String[] value() { return new String[0]; } @Override public boolean ignoreUnknown() { return false; } @Override public boolean allowGetters() { return false; } @Override public boolean allowSetters() { return false; }}; final Method method = Class.class.getDeclaredMethod("getDeclaredAnnotationMap", null);method.setAccessible(true); final Map<Class<? extends Annotation>, Annotation> annotations = (Map<Class<? extends Annotation>, Annotation>) method.invoke(SomeClass.class, null);annotations.put(JsonIgnoreProperties.class, modifiedAnnotation);
添加回答
举报
0/150
提交
取消