Javassist
动态生成字节码技术。操作java字节码的工具有两个比较流行,一个是ASM,一个是Javassit 。
ASM
:直接操作字节码指令,执行效率高,要是使用者掌握Java类字节码文件格式及指令,对使用者的要求比较高。Javassist
: 提供了更高级的API,执行效率相对较差,但无需掌握字节码指令的知识,对使用者要求较低。
Javassist
是一个开源的分析、编辑和创建Java字节码的类库。Javassist
中最为重要的是ClassPool
,CtClass
,CtMethod
以及 CtField
这几个类。
ClassPool
:一个基于HashMap实现的CtClass对象容器,其中键是类名称,值是表示该类的CtClass对象。默认的ClassPool使用与底层JVM相同的类路径,因此在某些情况下,可能需要向ClassPool添加类路径或类字节。CtClass
:表示一个类,这些CtClass
对象可以从ClassPool
获得。CtMethods
:表示类中的方法。CtFields
:表示类中的字段。
下面,编写一个简单的实例,演示一下Javassist
的使用:
- 先编写一个model类,取名为
Student
,代码如下:
public class Student {
}
这里需要说明一下的是,这是一个空的class,没有任何的属性和方法。下面我们就使用Javassist
,进行动态编程。
Javassist
的使用代码,代码如下:
public class TestJavassitCompiler {
public static void main(String[] args) throws Exception{
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.makeClass("com.hui.wang.dubbo.learn.provider.javassist.model.Student");
//添加属性:private String name
CtField nameField = new CtField(pool.getCtClass("java.lang.String"), "name", ctClass);
nameField.setModifiers(Modifier.PRIVATE);
ctClass.addField(nameField);
//添加属性:private int age
CtField ageField = new CtField(pool.getCtClass("int"), "age", ctClass);
ageField.setModifiers(Modifier.PRIVATE);
ctClass.addField(ageField);
//getter和setter
ctClass.addMethod(CtNewMethod.getter("getName", nameField));
ctClass.addMethod(CtNewMethod.setter("setName", nameField));
ctClass.addMethod(CtNewMethod.getter("getAge", ageField));
ctClass.addMethod(CtNewMethod.setter("setAge", ageField));
//创建构造器
CtConstructor ctConstructor = new CtConstructor(new CtClass[] {}, ctClass);
String body = new StringBuilder("{\nthis.age = 1;\nthis.name = \"hui.wang\";\n}").toString();
ctConstructor.setBody(body);
ctClass.addConstructor(ctConstructor);
//普通方法
CtMethod ctMethod = new CtMethod(CtClass.voidType, "commonMethod", new CtClass[] {}, ctClass);
ctMethod.setModifiers(Modifier.PUBLIC);
ctMethod.setBody(new StringBuilder("{\n System.out.println(\"this is a common method\"); \n" +
"\n System.out.println(this.getAge()); \n}").toString());
ctClass.addMethod(ctMethod);
Class<?> clazz = ctClass.toClass();
Object obj = clazz.newInstance();
//方法调用
obj.getClass().getMethod("commonMethod", new Class[] {}).invoke(obj, new Object[] {});
}
}
打印结果为:
this is a common method
1
参考