添加字段并使用 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 加载的精确时间,其微妙之处已在
中讨论
在下面的示例中,我想通过不执行 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 加载的精确时间,其微妙之处已在