添加字段并使用 Javassist 动态更改其值

Add a field and change its value dynamically using Javassist

在下面的示例中,我想通过不执行 class B 的超级方法来执行 class A 的超级方法。为此,我正在使用 Javassist 并且我能够在 SO post 的帮助下这样做。但是我在调​​用class的super方法时无法传递值 A.我提供了一个变量name作为参数,同时调用hi()的class C 在下面的示例中,但它没有在我使用 Javassist 生成的变量 myVar 中引用。

生成的输出:

Ok thing C MyData
Important thing A null

预期输出:

Ok thing C MyData
Important thing A MyData

非常感谢任何帮助。

源代码:

class A {
    public void hi(String first) {
        System.out.println("Want Important thing A " + first);
    }
}

class B extends A {
    public void hi(String second) {
        System.out.println("Don't want TERRIBLE THING B " + second);
        super.hi(second);
    }
}

class C extends B {
    public void hi(String third) {
        System.out.println("Want important thing C " + third);
        super.hi(third);
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        String name = "MyData";
        CtClass cc = ClassPool.getDefault().get("mypackage.B");
        CtMethod m1 = cc.getDeclaredMethod("hi");
        cc.removeMethod(m1);
        CtMethod m2 = CtNewMethod.copy(m1, cc, null);
        CtClass stringVar = ClassPool.getDefault().get("java.lang.String");
        CtField f = new CtField(stringVar , "myVar", cc);
        cc.addField(f);
        m2.setBody("{ /* override method B.hi() body */ return super.hi(myVar);}", "this", m1.getName());
        cc.addMethod(m2);
        cc.toClass();
        C obj = new C();
        obj.hi(name);
    }
}

既然要传递参数值给super方法调用,就不用再引入新字段了

根据this tutorial你可以使用</code>来引用第一个参数,而不考虑原始源代码的名称(这也解决了名称可能未存储在[=中的问题24=] 文件).</p> <p>所以方法体看起来像 <code>"{ return super.hi(); }"。本教程还解释说 Javassist 与普通的 Java 源代码不同,它允许将此语法用于 void 方法。

重要的是要记住,通过在加载另一个版本之前具体化替代版本来替换 classes 的方法非常脆弱,尤其是在使用同样使用更改了 class(或它的子class)。这取决于 class 加载的精确时间,其微妙之处已在

中讨论