功能
动态生成新的类
动态改变某个类的结构(增删改查 新的属性和方法)
优势
比反射开销小
javaAasist性能高于反射低于ASM
常见的类库
BCEL
ASM
CGLIB
Javassist//下载地址http://jboss-javassist.github.io/javassist/
javassist主要有CtClass,CtMethod,CtFile。用于执行和jdk反射API中的java.lang.Class,java.lang.reflect.Method,java.lang.reflect.Method.Field相同的操作
创建一个类
package study;
import java.io.IOException;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
import javassist.NotFoundException;
/** * 测试javassist生成一个新的类 * * @author http://blog.csdn.net/thewaiting * */
public class Text {
public static void main(String[] args) throws CannotCompileException, NotFoundException, IOException {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass("study2.Person");
// 创建属性
CtField f = CtField.make("private int id;", cc);
CtField f2 = CtField.make("private String name;", cc);
cc.addField(f);
cc.addField(f2);
// 创建方法
CtMethod m = CtMethod.make("public int getId(){return this.id;}", cc);
CtMethod m2 = CtMethod.make("public void setId(int id){this.id = id;}", cc);
cc.addMethod(m);
cc.addMethod(m2);
// 添加构造器
CtConstructor c = new CtConstructor(new CtClass[] { CtClass.intType, pool.get("java.lang.String") }, cc);
// 构造方法体
c.setBody("{this.id = id;this.name = name;}");
cc.addConstructor(c);
// 放入工作空间
cc.writeFile("D:/text");
System.out.println("生成的类用反编译工具查看");
}
}
获取一个类
package study;
public class Person {
private int id;
private String name;
public Person() {
}
public Person(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
javassist的用法
package study;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AllPermission;
import java.util.Arrays;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtBehavior;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMember;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.Modifier;
import javassist.NotFoundException;
/** * * 测试javassist的api * * @author http://blog.csdn.net/thewaiting * */
public class Text {
/** * 处理类的基本用法 * * @throws NotFoundException * @throws CannotCompileException * @throws IOException */
public static void text1() throws NotFoundException, IOException, CannotCompileException {
// 获得池对象
ClassPool pool = ClassPool.getDefault();
// 获得指定某个类
CtClass cc = pool.get("study.Person");
byte[] bytes = cc.toBytecode();
System.out.println(Arrays.toString(bytes));
System.out.println(cc.getName());// 获得类名
System.out.println(cc.getSimpleName());
System.out.println(cc.getSuperclass());// 获得父类
}
/** * 测试产生新的方法 * * @throws NotFoundException * @throws CannotCompileException * @throws IllegalAccessException * @throws InstantiationException * @throws SecurityException * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalArgumentException */
public static void text2()
throws NotFoundException, CannotCompileException, InstantiationException, IllegalAccessException,
NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
// 获得池对象
ClassPool pool = ClassPool.getDefault();
// 获得指定某个类
CtClass cc = pool.get("study.Person");
// CtMember m = CtNewMethod.make("public int add(int a,int b){return
// a+b}", cc);
// 参数 指定返回类型 方法的名称 方法的参数
CtMember m = new CtMethod(CtClass.intType, "add", new CtClass[] { CtClass.intType, CtClass.intType }, cc);
// 是什么方法
m.setModifiers(Modifier.PUBLIC);
((CtBehavior) m).setBody("{return $1+$2;}");// $0 为this $后为形参
cc.addMethod((CtMethod) m);
// 通过反射调用新生成的方法
Class clazz = cc.toClass();
Object obj = clazz.newInstance();// 通过调用person无参构造,创建新的person对象
Method method = clazz.getDeclaredMethod("add", int.class, int.class);
System.out.println(method.invoke(obj, 200, 300));
}
/** * 修改方法已经有的信息 * * @throws NotFoundException * @throws CannotCompileException * @throws NoSuchMethodException * @throws SecurityException * @throws InstantiationException * @throws IllegalAccessException * @throws IllegalArgumentException * @throws InvocationTargetException */
public static void text3()
throws NotFoundException, CannotCompileException, NoSuchMethodException, SecurityException,
InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// 获得池对象
ClassPool pool = ClassPool.getDefault();
// 获得指定某个类
CtClass cc = pool.get("study.Person");
CtMethod cm = cc.getDeclaredMethod("say", new CtClass[] { CtClass.intType });// 第二个参数为数组
// 修改方法 在方法前加 在方法的第几行加 在方法后面加
cm.insertBefore("System.out.println($1+\" start\");");
cm.insertAt(8, "int b = 3;System.out.println(b);");
cm.insertAfter("System.out.println($1+\" end\");");
// 通过反射调用新生成的方法
Class clazz = cc.toClass();
Object obj = clazz.newInstance();
Method m = clazz.getDeclaredMethod("say", int.class);
System.out.println(m.invoke(obj, 12));
}
/** * 属性的操作 * * @throws NotFoundException * @throws CannotCompileException */
public static void text4() throws NotFoundException, CannotCompileException {
// 获得池对象
ClassPool pool = ClassPool.getDefault();
// 获得指定某个类
CtClass cc = pool.get("study.Person");
// CtField field = CtField.make("private int id;", cc);
CtField f1 = new CtField(CtClass.intType, "age", cc);
f1.setModifiers(Modifier.PRIVATE);
// 加上值
cc.addField(f1, "10");
// 获取值
// cc.getDeclaredField("name");
// 增加get set 方法
cc.addMethod(CtNewMethod.getter("getAge", f1));
cc.addMethod(CtNewMethod.getter("setAge", f1));
}
/** * 构造方法的操作 * * @throws NotFoundException */
public static void text5() throws NotFoundException {
// 获得池对象
ClassPool pool = ClassPool.getDefault();
// 获得指定某个类
CtClass cc = pool.get("study.Person");
CtConstructor[] cs = cc.getConstructors();
for (CtConstructor c : cs) {
System.out.println(c.getLongName());
//c.insertBefore("");添加方法
}
}
public static void text6() throws NotFoundException, ClassNotFoundException {
CtClass cc = ClassPool.getDefault().get("study.Person");
Object[] all = cc.getAnnotations();
Author a = (Author) all[0];
String name = a.name();
int year = a.year();
System.out.println("name "+name + " year "+ year);
//能进一步操作
}
public static void main(String[] args) throws NotFoundException, IOException, CannotCompileException,
InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException,
IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
// text01();
// text2();
// text3();
// text4();
// text5();
text6();
}
}