我正在尝试使用javassist库在运行时修改java注释的属性。我所做的更改在javassist中可见,但在其他代码块中则不可见。
这是示例groovy脚本:
@Grab(version = "3.20.0-GA", group = "org.javassist", module = "javassist")
import javassist.ClassPool
import javassist.CtClass
import javassist.CtMethod
import javassist.bytecode.AnnotationsAttribute
import javassist.bytecode.ClassFile
import javassist.bytecode.ConstPool
import javassist.bytecode.annotation.StringMemberValue
import java.lang.annotation.*
import java.lang.reflect.Method
@Documented
@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RestApiMethod {
public String description();
}
public class SampleController<T> {
Class<T> resource
SampleController(Class<T> resource) {
this.resource = resource
}
@RestApiMethod(description = "Do something on #{ApiClass.name}")
public void doSomething() {
println("Dummy Output")
}
}
public class ModifyAnnotation {
public static void addRestApiMethodAnnotationToMethod(SampleController controller, Method method,
String name, String value) {
//pool creation
ClassPool pool = ClassPool.default
//get CtClass
CtClass cc = pool.getCtClass(controller.class.name)
//looking for the method to apply the annotation on
CtMethod ctMethod = cc.methods.find { it.name.equals(method.name) }
// create the annotation
ClassFile ccFile = cc.classFile
ConstPool constPool = ccFile.constPool
javassist.bytecode.annotation.Annotation annotation = new javassist.bytecode.annotation.Annotation(RestApiMethod.name, constPool)
annotation.addMemberValue(name, new StringMemberValue(value, ccFile.getConstPool()))
// add the annotation
AnnotationsAttribute attribute = getAnnotationsAttribute(ctMethod)
System.out.println("Before modification+++++++++++++++++++$attribute")
attribute.addAnnotation(annotation)
System.out.println("After modification+++++++++++++++++++$attribute")
//Write class to file
cc.writeFile()
cc.defrost()
}
private static AnnotationsAttribute getAnnotationsAttribute(CtMethod ctMethod) {
return ctMethod.methodInfo.attributes.find { it instanceof AnnotationsAttribute }
}
}
Closure fetchDoSomethingMethod = {
SampleController.methods.find { it.name.equals("doSomething") }
}
println(fetchDoSomethingMethod().getAnnotation(RestApiMethod).description())
ModifyAnnotation.addRestApiMethodAnnotationToMethod(new SampleController(Integer), fetchDoSomethingMethod(), "description", "New Value")
println(fetchDoSomethingMethod().getAnnotation(RestApiMethod).description())
我有一个简单的注释RestApiMethod
,我在SampleController
内的方法上使用它。当我运行此脚本时,它会打印:
Do something on #{ApiClass.name}
Before modification+++++++++++++++++++@RestApiMethod(description="Do something on #{ApiClass.name}")
After modification+++++++++++++++++++@RestApiMethod(description="New Value")
Do something on #{ApiClass.name}
以及随后执行的打印:
Do something on #{ApiClass.name}
Before modification+++++++++++++++++++@RestApiMethod(description="New Value")
After modification+++++++++++++++++++@RestApiMethod(description="New Value")
Do something on #{ApiClass.name}
ModifyAnnotation.addRestApiMethodAnnotationToMethod
内的代码读取更新的代码,但如果我使用reflection api来获取doSomething
上的注释,它仍会返回旧值。