起初一看,我印象中是不行的,因为我一直以为XXX.class.getAnnotation(XXXAnnotation.class)这个方法是一个native方法直到刚自己去看了一眼,哎呀,不是native方法啊好家伙,源来氏Class类中有一个私有内部静态类AnnotationData负责存储Class的注解里的值(前提你的注解是RetentionPolicy.RUNTIME的),当然存法也很简单就是用一个map存储了注解类型和注解实例所以看起来直接去修改对应Class的AnnotationData属性中的annotations map里的注解实例就可以了但是其实不然,因为我们反射是拿不到反射相关类的属性的,例如Class,Field这些,不然那可不乱了套了(相当于搁这搁这这种套娃操作了...),因此呢只能再换个思路我们可以注意到,虽然注解实例缓存在Class中,但是它确实可以通过getAnnotation获取到对应的实例,而这个实例恰好是一个代理对象,其实也就是用咱们jdk动态代理做的,只用debug一看就很清楚了既然是代理对象,那肯定有对应的InvocationHandler啊,既然代理对象能够实现原注解的所有功能,那意味着其对应的InvocationHandler肯定也包含了该注解的所有功能。果不其然,注解对应InvocationHandler是AnnotationInvocationHandler,这个类就很憨厚了,其中的memberValues属性就是我们需要的,怎么证实呢?比如我们有个注解TestAnnotation@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface TestAnnotation { String value(); }注解到一个叫Test的类上,value值就写成haha我们直接通过getAnnotation拿到对应的注解,再用Proxy.getInvocationHandler拿到对应的InvocationHandlerTestAnnotation testAnnotation = Test.class.getDeclaredAnnotation(TestAnnotation.class); InvocationHandler invocationHandler = Proxy.getInvocationHandler(testAnnotation);这个debug一看就很明显啦memberValues中就藏着我们的目标,所以我们可以直接通过反射修改它就可以了,比如这样TestAnnotation annotation = Test.class.getAnnotation(TestAnnotation.class); System.out.println("before value: " + annotation.value()); InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation); Field value = invocationHandler.getClass().getDeclaredField("memberValues"); value.setAccessible(true); Map<String, Object> memberValues = (Map<String, Object>) value.get(invocationHandler); memberValues.put("value", "i am new value"); annotation = Test.class.getAnnotation(TestAnnotation.class); System.out.println("after value: " + annotation.value());最终打印效果:但是这样有个问题,什么呢?就是注解不仅仅是可以注解在类上的,也可以注解在字段上,方法上,所以我后面看了一下字段和方法上是怎么实现这个getAnnotation,那肯定就不是用AnnotationData啦,毕竟人家是Class的内部类Field呢是内部有个私有declaredAnnotations属性,是Map<Class<? extends Annotation>, Annotation>的类型,那这个就和AnnotationData里的annotations类似啦而Method是其父类Executable有个declaredAnnotations属性,还是Map<Class<? extends Annotation>, Annotation>类型那说明无论是怎么获取注解,都是从某个地方的Map<Class<? extends Annotation>, Annotation>缓存中获取。那怎么把不同地方,例如类,方法,字段聚合在一个工具类中呢?铛铛铛!恰好有个顶层的接口把它们聚在了一起AnnotatedElement。因此工具方法应运而生(其实他们的getAnnotation方法就是来自AnnotatedElement接口的方法)public static void modify(AnnotatedElement element, Class<? extends Annotation> annotationClass, String key, Object value) throws NoSuchFieldException, IllegalAccessException { Annotation annotationToBeModified = element.getAnnotation(annotationClass); if (annotationToBeModified == null) return; InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotationToBeModified); Field memberValuesField = invocationHandler.getClass().getDeclaredField("memberValues"); memberValuesField.setAccessible(true); Map<String, Object> memberValues = (Map<String, Object>) memberValuesField.get(invocationHandler); memberValues.put(key, value); }参数也很好理解,AnnotatedElement就是被注解的地方啦,如果呢你是注解的类,就传Class,注解的方法,就传某个Method,注解的是字段,就传Field,就算注解的参数,那就传某个Parameter,总之理论上啥都够啦最后题主提到的MySQL那就不是大问题啦,毕竟它只是一个数据库而已,如果真有某个工具可以实现题主的需求,那提供这个工具的人也太嘞了。。。竟然必须要MySQL,所以啊,这个问题最大的点应该还是如何实现运行时修改注解里的值,不过最后实现下来看起来也没多少代码,只是一个小工具,可以放到自己项目中进行一些组装成为其他业务组件的一个部分吧。那就酱。。。o( ̄▽ ̄)d
起初一看,我印象中是不行的,因为我一直以为
XXX.class.getAnnotation(XXXAnnotation.class)
这个方法是一个native
方法直到刚自己去看了一眼,哎呀,不是

native
方法啊好家伙,源来氏


Class
类中有一个私有内部静态类AnnotationData
负责存储Class
的注解里的值(前提你的注解是RetentionPolicy.RUNTIME
的),当然存法也很简单就是用一个map
存储了注解类型和注解实例所以看起来直接去修改对应
Class
的AnnotationData
属性中的annotations map
里的注解实例就可以了但是其实不然,因为我们反射是拿不到反射相关类的属性的,例如
Class
,Field
这些,不然那可不乱了套了(相当于搁这搁这这种套娃操作了...),因此呢只能再换个思路我们可以注意到,虽然注解实例缓存在

Class
中,但是它确实可以通过getAnnotation
获取到对应的实例,而这个实例恰好是一个代理对象,其实也就是用咱们jdk
动态代理做的,只用debug
一看就很清楚了既然是代理对象,那肯定有对应的
InvocationHandler
啊,既然代理对象能够实现原注解的所有功能,那意味着其对应的InvocationHandler
肯定也包含了该注解的所有功能。果不其然,注解对应

InvocationHandler
是AnnotationInvocationHandler
,这个类就很憨厚了,其中的memberValues
属性就是我们需要的,怎么证实呢?比如我们有个注解
TestAnnotation
注解到一个叫

Test
的类上,value
值就写成haha
我们直接通过
getAnnotation
拿到对应的注解,再用Proxy.getInvocationHandler
拿到对应的InvocationHandler
这个
debug
一看就很明显啦memberValues
中就藏着我们的目标,所以我们可以直接通过反射修改它就可以了,比如这样最终打印效果:

但是这样有个问题,什么呢?就是注解不仅仅是可以注解在类上的,也可以注解在字段上,方法上,所以我后面看了一下字段和方法上是怎么实现这个
getAnnotation
,那肯定就不是用AnnotationData
啦,毕竟人家是Class
的内部类Field
呢是内部有个私有declaredAnnotations
属性,是Map<Class<? extends Annotation>, Annotation>
的类型,那这个就和AnnotationData
里的annotations
类似啦而
Method
是其父类Executable
有个declaredAnnotations
属性,还是Map<Class<? extends Annotation>, Annotation>
类型那说明无论是怎么获取注解,都是从某个地方的
Map<Class<? extends Annotation>, Annotation>
缓存中获取。那怎么把不同地方,例如类,方法,字段聚合在一个工具类中呢?铛铛铛!恰好有个顶层的接口把它们聚在了一起
AnnotatedElement
。因此工具方法应运而生(其实他们的getAnnotation
方法就是来自AnnotatedElement
接口的方法)参数也很好理解,
AnnotatedElement
就是被注解的地方啦,如果呢你是注解的类,就传Class
,注解的方法,就传某个Method
,注解的是字段,就传Field
,就算注解的参数,那就传某个Parameter
,总之理论上啥都够啦最后题主提到的
MySQL
那就不是大问题啦,毕竟它只是一个数据库而已,如果真有某个工具可以实现题主的需求,那提供这个工具的人也太嘞了。。。竟然必须要MySQL
,所以啊,这个问题最大的点应该还是如何实现运行时修改注解里的值,不过最后实现下来看起来也没多少代码,只是一个小工具,可以放到自己项目中进行一些组装成为其他业务组件的一个部分吧。那就酱。。。o( ̄▽ ̄)d