使用javassist的ByteCode更改在代码的其他部分中不可见

时间:2016-02-10 15:33:18

标签: java groovy javassist

我正在尝试使用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上的注释,它仍会返回旧值。

0 个答案:

没有答案