Javassist使用
一.简介
Javassist是一个开源的,可以在运行期分析、编辑和创建Java字节码的类库。其主要的优点,在于简单,而且快速,直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。而其他的一些工具都需要直接跟虚拟机指令打交道。
二.使用
我们此次的demo:在com.cwj.javassist_module包下,有一个Model类,其类本身有一个RUNTIME的自定义注解ValueAnnotation,内部有一个静态方法stM1,四个非静态方法,还有两个内部类,一个是静态内部类Nestd2,一个是非静态内部类Nested1
@ValueAnnotation("heheda")
public class Model {
public static void stM1() {
}
public void method1() {
String res = method2("a", 2);
}
public void method1(String str, int idx) {
}
public String method2(String str, int idx) {
return str;
}
private String method3(String str, int idx) {
return str + idx;
}
public class Nested1 {
}
public static class Nested2 {
}
}
我们就以该demo为基础,看一下javassist如何操作字节码
(一)class
javassist通过其ClassPool对象,保存着加载出来的所有类信息,该对象默认寻找的classpath为系统设置的classpath,当寻找具体类时,会在这些classpath目录下寻找;每个类的信息被封装到一个CtClass对象中
1.获取
//获取默认的ClassPool对象
ClassPool classPool = ClassPool.getDefault()
//添加包含目标类的classpath到ClassPool中
ClassPath classPath = classPool.appendClassPath(path)
//通过ClassPool,到classpath中,寻找指定类名的类,返回CtClass对象
CtClass ctClass = classPool.get("com.cwj.javassis_module.Model")
-
一定要确保有classpath包含该类,否则会因为找不到类而抛异常
-
classname一定是类的全限定类名,即packageName.className
-
CtClass对象类似于java的Class对象,用于获取类的一些操作(如获取声明的所有方法、field等),并且API也大同小异
if (ctClass.isFrozen()) {
ctClass.defrost()
}
在使用CtClass进行编辑操作前,最好判断一下它的状态,它有一个frozen状态,当一些操作进行后(比如保存更改),就为true,把CtClass对象"冻结"起来不让操作;如果是该状态,我们可以通过defrost方法进行解冻,否则在frozen状态下进行操作会抛异常
2.新建
CtClass newClass = classPool.makeClass("com.cwj.inject.NewClass")
//设置父类
newClass.setSuperclass(classPool.get