Use javassist to modify fields that use getters and setters in a class constructor

我的未来我决定 提交于 2019-12-24 18:47:14

问题


I am trying to modify the following fields in a class constructor using javassist :

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

I want to prepend text to the 2 labels. The text can be accessed and set using getText() and setText().

How could I achieve this?


回答1:


The simplest approach is to use the ability to modify the constructor body with java code and let javassist create the bytecode.

So you can easily do something like:

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/");

Also keep in mind that if the prefix you'll be adding, instead of a String is a static field in other class you must give the full qualified name of that class, for example: .append(package1.package2.SomeClass.SomeField).

This is needed because imports are only at source level, when you look at the JVM bytecode all class references are to the full qualified name.

More information on how to achieve this kind of modifications with Javassist can be found in the javasssist's documentation, section 4.1 Inserting source text at the beginning/end of a method body

UPDATE

Whenever you are writing Java code for javassist to inject, keep in mind that you must use full qualified class names, otherwise javassist's classpool wouldn't be able to find the classes resulting in a javassist.CannotCompileException.



来源:https://stackoverflow.com/questions/13715986/use-javassist-to-modify-fields-that-use-getters-and-setters-in-a-class-construct

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!