我正在尝试使用javassist修改类构造函数中的以下字段:
Label Label1 = new Label(new StringBuilder().append(user.name));
Label Label2 = new Label(new StringBuilder().append(user.time.toString());
我想在2个标签前加上文字。可以使用getText()和setText()来访问和设置文本。
我怎么能实现这个目标?
答案 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
的类。