Javassist 介绍
Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态AOP框架。javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。
javassit 概念
Javassist中最为重要的是ClassPool,CtClass ,CtMethod 以及 CtField这几个类。
ClassPool:一个基于HashMap实现的CtClass对象容器,其中键是类名称,值是表示该类的CtClass对象。默认的ClassPool使用与底层JVM相同的类路径,因此在某些情况下,可能需要向ClassPool添加类路径或类字节。
CtClass: (compile-time class) 表示一个类,这些CtClass对象可以从ClassPool获得。
CtMethods:表示类中的方法。
CtFields :表示类中的字段。
简单示例
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("test.Rectangle");
cc.setSuperclass(pool.get("test.Point"));
cc.writeFile();
这个程序首先获得一个ClassPool对象,它用Javassist控制字节码修改。ClassPool对象是表示类文件的CTClass对象的容器。它根据需要读取一个类文件来构造一个CTClass对象,并记录所构造的对象以供以后响应访问。要修改类的定义,用户必须首先从ClassPool对象获取对表示该类的CTClass对象的引用。类池中的get()用于此目的。对于上面所示的程序,CTClass对象表示一个类测试。矩形是从ClassPool对象获得的,它被分配给一个变量cc。getdefault()返回的classpool对象搜索默认的系统搜索路径。
动态代码示例
以下是动态生成类并运行动态生成的方法:
package com.robin.assist;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import javassist.NotFoundException;
import javassist.bytecode.AccessFlag;
public class DynamicGenerateClass {
public static void main(String[] args) {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass("com.robin.assit.test.Retangle");// 创建类
cc.setInterfaces(new CtClass[] { pool.makeInterface("java.lang.Cloneable") });// 让类实现Cloneable接口
try {
CtField f = new CtField(CtClass.intType, "id", cc);
// 生成一个int 类型的id属性
f.setModifiers(AccessFlag.PUBLIC);// 设置访问修饰符
cc.addField(f);// 将属性设置到类上
// 添加构造方法
CtConstructor constructor = CtNewConstructor.make("public Retangle(int id){this.id=id;}", cc);
cc.addConstructor(constructor);
// 添加方法
CtMethod alohaMethod = CtNewMethod
.make("public void aloha(String hello){" + "System.out.println(hello);" + "}", cc);
cc.addMethod(alohaMethod);
// 将生成的.class 文件保存到磁盘
//cc.writeFile();
//验证结果
Class ct=cc.toClass();
Field[] fields = ct.getFields();
System.out.println("attribute name:" + fields[0].getName() + ",attribute type:" + fields[0].getType());
Method aloha=ct.getMethod("aloha",new Class[] {String.class});
//动态调用
Constructor<?> con=ct.getConstructor(int.class);
aloha.invoke(con.newInstance(1), "hello world");
} catch (CannotCompileException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
输出结果
attribute name:id,attribute type:int
hello world
http://www.javassist.org/tutorial/tutorial.html