Javassist 是一个操作 Java 字节码的类库,通过它可以直接操作 Java 的 .class
字节码文件。
使用 Javassist 创建一个 class 文件
Javassist.CtClass
是类文件的抽象。 CtClass
(compile-time class)负责处理一个类文件 。下面是个简单的例子:
1 | ClassPool pool = ClassPool.getDefault(); |
运行之后,找到生成的类文件 /Users/kail/_test/xyz/kail/blog/CodeClass.class
,反编译后的效果如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26package xyz.kail.blog;
public class CodeClass {
private String name = "init";
public void setName(String var1) {
this.name = var1;
}
public String getName() {
return this.name;
}
public CodeClass() {
this.name = "Kail";
}
public CodeClass(String var1) {
this.name = var1;
}
public void execute() {
System.out.println(this.name);
}
}
调用生成的类
上面生成了一个类,如何调用这个类呢? 例子如下:
实例化调用
1 | ... 省略生成类的部分 |
读取文件调用
1 | ClassPool pool2 = ClassPool.getDefault(); |
通过接口方式调用
以上生成类之后,通过反射的方式调用,个人感觉实际场景比较少,因为反射的性能不是很好。实际上可以定义一个接口,通过接口调用,如下:
先定义给一个接口
1 | package xyz.kail.blog; |
1 | ClassPool pool = ClassPool.getDefault(); |
使用 Javassist 修改现有的类
通过代码去凭空生成一个类估计很少用到,因为这哪有直接写一个类方便。
主要的场景是修改一个现有的类,给类增加功能,如AOP等。
在方法前后插入代码
1 | CtMethod executeMethod = ctClass.getDeclaredMethod("execute"); |
清空方法体使方法无效
1 | CtMethod executeMethod = ctClass.getDeclaredMethod("execute"); |
其它更复杂的修改请参考官方文档 Introspection and customization。