使用javassist修改在类构造函数中使用getter和setter的字段

时间:2012-12-05 03:48:38

标签: java constructor javassist

我正在尝试使用javassist修改类构造函数中的以下字段:

Label Label1 = new Label(new StringBuilder().append(user.name));
Label Label2 = new Label(new StringBuilder().append(user.time.toString());

我想在2个标签前加上文字。可以使用getText()和setText()来访问和设置文本。

我怎么能实现这个目标?

1 个答案:

答案 0 :(得分:2)

最简单的方法是使用java代码修改构造函数体的能力,让javassist创建字节码。

因此,您可以轻松地执行以下操作:

ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.get("package1.package2.ClassToInject");
    /* Notice that in this case I'm going for the default constructor
     * If you want another constructor you just have to materialize the CtClass, for
     * each parameter and pass them in the CtClass Array
     */
CtConstructor declaredConstructor = ctClass.getDeclaredConstructor(new CtClass[] {}); 
 /* Now that you have your constructor you can use insertAfter(), this means, it 
      * will be the last thing to be executed in the constructor. We'll rewrite the 
      * label1 field with our new value. Notice that the string in insertAfter 
      * argument is a regular, valid java code line.
      */
    declaredConstructor.insertAfter("Label1 = new package3.package4.Label(new StringBuilder().append(\"somePrefixMayBeAStringOrAVariableInScope\").append(user.name));");

    // and finally we write the bytecode
ctClass.writeFile("/somePathToPutTheInjectedClassFile/");

另请注意,如果您要添加的前缀,而不是String是其他类中的静态字段,则必须提供该类的完全限定名称,例如:.append(package1.package2.SomeClass.SomeField)

这是必需的,因为imports仅在源级别,当您查看JVM字节码时,所有类引用都是完全限定名称。

有关如何使用Javassist实现此类修改的更多信息,请参阅javasssist的文档,4.1 Inserting source text at the beginning/end of a method body部分

<强>更新

每当您编写要注入的javassist的Java代码时,请记住必须使用完全限定的类名,否则javassist的classpool将无法找到导致javassist.CannotCompileException的类。