package java_217_字节码操作_javaassist库_介绍_API详解_练习;
import java.lang.reflect.Method; import java.util.Arrays; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; import javassist.CtField; import javassist.CtMethod; import javassist.CtNewMethod; import javassist.Modifier; import javassist.NotFoundException; import sun.security.x509.AuthorityInfoAccessExtension; /**
测试javaassist的API:
javaassist库的API详解:
1.修改已有方法的方法体(插入代码到已有的方法体)
2.新增方法
3.删除方法 / public class Demo02 { /*
处理类的基本用法
@throws Exception */ public static void test01() throws Exception{ //获取对象 ClassPool pool = ClassPool.getDefault(); //获得某个指定的类 CtClass cc = pool.get(“java_217_字节码操作_javaassist库_介绍_API详解_练习.Emp”); 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());//获取父类 System.out.println(cc.getInterfaces());//获取接口;因为没有加入接口;显示的是一个地址 } /**
测试新产生的方法
@throws Exception */ public static void test02() throws Exception{
//获取对象 ClassPool pool = ClassPool.getDefault(); //获得某个指定的类 CtClass cc = pool.get(“java_217_字节码操作_javaassist库_介绍_API详解_练习.Emp”);
//CtMethod m = CtNewMethod.make(“public int add(int a,int b){return a+b;}”, cc);
//如果一个CtClass对象通过writeFile(),toClass()或者toByteCode()转换成class文件,那么javassist会冻结这个CtClass对象。 //后面就不能修改这个CtClass对象了。这样是为了警告开发者不要修改已经被JVM加载的class文件,因为JVM不允许重新加载一个类。加入cc.defrost();问题便得到了解决。
cc.defrost(); CtMethod m = new CtMethod(CtClass.intType,“add”, new CtClass[]{CtClass.intType,CtClass.intType}, cc);
m.setModifiers(Modifier.PUBLIC); m.setBody("{System.out.println(“新的数据”);return $1+$2;}");//出现报错 把a+b换成占位符$1+$2 cc.addMethod(m);
//通过反射调用新的方法 Class clazz = cc.toClass();//转化为class对象 //创建新的对象 Object obj = clazz.newInstance();//通过调用Emp无参构造器,创建新的Emp对象 //获得方法 Method method = clazz.getDeclaredMethod(“add”, int.class,int.class); Object result = method.invoke(obj, 200,300); System.out.println(result);
} /**
@throws Exception修改已有的方法的信息;修改方法体的内容*/ public static void test03() throws Exception{ //获取对象 ClassPool pool = ClassPool.getDefault(); //获得某个指定的类 CtClass cc = pool.get(“java_217_字节码操作_javaassist库_介绍_API详解_练习.Emp”); cc.defrost(); CtMethod cm = cc.getDeclaredMethod(“sayHello”,new CtClass[]{CtClass.intType});//new CtClass[]{CtClass.intType};传进数组
//在("sayHello:"+a);前面写入内容 cm.insertBefore("System.out.println($1);System.out.println(\"开始\");"); //在("sayHello:"+a);后面加入内容 cm.insertAfter("System.out.println(\"结束\");"); //在某一行加入内容 cm.insertAt(12, "int b=3;System.out.println(\"b=\"+b);");//在System.out.println("sayHello:"+a);前面加入内容 //通过反射调用新的方法 Class clazz = cc.toClass();//转化为class对象 //创建新的对象 Object obj = clazz.newInstance();//通过调用Emp无参构造器,创建新的Emp对象 //获得方法 Method method = clazz.getDeclaredMethod("sayHello", int.class); Object result = method.invoke(obj,300); System.out.println(result);//这个没有返回值 所以控制台打印为null} /**
修改属性
@param args
@throws Exception */ public static void test04() throws Exception{ //获取对象 ClassPool pool = ClassPool.getDefault(); //获得某个指定的类 CtClass cc = pool.get(“java_217_字节码操作_javaassist库_介绍_API详解_练习.Emp”); cc.defrost();
//CtField f1 = CtField.make(“private int empno;”, cc);//可以用上节课的这个方法 //或者 CtField f1 =new CtField(CtClass.intType, “salary”,cc);//salary薪水 f1.setModifiers(Modifier.PRIVATE);//修饰符 cc.addField(f1,“1000”);//1000是给empno添加个默认值即empno=1000; 不需要可以不写
/*//获取属性 //cc.getDeclaredField(“salary”);//获取指定的属性 //增加set与get方法 cc.addMethod(CtNewMethod.getter(“getSalary”, f1)); cc.addMethod(CtNewMethod.getter(“setSalary”, f1)); / /*
注意 :这里的具体实现高淇老师没讲,我研究了几天也没整明白. */} /**
获得构造器@param args@throws Exception */ public static void test05() throws Exception{ //获取对象 ClassPool pool = ClassPool.getDefault(); //获得某个指定的类 CtClass cc = pool.get(“java_217_字节码操作_javaassist库_介绍_API详解_练习.Emp”); cc.defrost(); CtConstructor[] cs = cc.getConstructors(); for(CtConstructor c:cs){ System.out.println(c.getLongName()); //构造器前面加代码 c.insertBefore(“System.out.println(“aa”);”); }} /**
获取注解@throws Exception */ public static void test06() throws Exception{ //获取对象 CtClass cc = ClassPool.getDefault().get(“java_217_字节码操作_javaassist库_介绍_API详解_练习.Emp”); 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 Exception { /test01(); System.out.println("=2"); test02();/ System.out.println("====3="); test03(); System.out.println("=4"); test04(); System.out.println("=5"); test05(); System.out.println("=6"); test06(); } } //----------------------------------------------------- package java_217_字节码操作_javaassist库_介绍_API详解_练习; /**
创建一个类
*/ @Author (name=“王伟”,year=2020) public class Emp {//Emp雇员 private int empno;//员工编号 private String ename;//员工姓名
public void sayHello(int a){//sayHello问好 System.out.println("sayHello:"+a); } public int getEmpno() { return empno; } public void setEmpno(int empno) { this.empno = empno; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public Emp() { super(); } public Emp(int empno, String ename) { super(); this.empno = empno; this.ename = ename; }} //------------------------------------------------ package java_217_字节码操作_javaassist库_介绍_API详解_练习;
public @interface Author {//interface接口 String name();
int year();} //结果----------------------------------------------- ====3= 300 开始 b=3 sayHello:300 结束 null =4 =5 java_217_字节码操作_javaassist库_介绍_API详解_练习.Emp() java_217_字节码操作_javaassist库_介绍_API详解_练习.Emp(int,java.lang.String) =6 name:王伟,year:2020