Javasist是一款字节码工具,可以用来动态修改字节码。反射机制也可以在运行时操作字节码,但是无法修改字节码。Javasist提供了动态修改字节码的能力。相比较于其他工具比如ASM,Javasist更加高层,不需要了解字节码文件的结构,但是运行效率不如ASM等更底层的工具。对于初学者而言,Javasist更加友好。
下面使用Javasist写一个小例子,在类方法前后各打印一条语句。
maven:
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.20.0-GA</version>
</dependency>
待增强的类:
public class Service {
public void service(){
System.out.println("doService");
}
}
增强代码:
public class Main {
public static void main(String args[]) throws NotFoundException,
CannotCompileException,
IllegalAccessException,
InstantiationException,
IOException {
ClassPool classPool = ClassPool.getDefault();
CtClass clz = classPool.get("com.liyao.test.Service");
CtMethod method = clz.getDeclaredMethod("service");
method.insertBefore("System.out.println(\"before execute!!!\");");
method.insertAfter("System.out.println(\"after execute!!!\");");
clz.writeFile();
Service s = (Service) clz.toClass().newInstance();
s.service();
}
}
运行结果:
before execute!!!
doService
after execute!!!
Process finished with exit code 0
上述代码还将新的class文件输出到文件中,反编译看下:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.liyao.test;
public class Service {
public Service() {
}
public void service() {
System.out.println("before execute!!!");
System.out.println("doService");
Object var2 = null;
System.out.println("after execute!!!");
}
}
可以看到,确实是修改后的class。