基于javassist进行动态编程过程解析
今天在研究dubbo时,发现一个新的知识点,可以使用javassist包进行动态编程,hibernate也使用该包进行编程。晚上百度了很多资料,将它的特性以代码的形式展现出来。
packagecom.zhi.demo; importjava.lang.reflect.Field; importjavassist.ClassPool; importjavassist.CtClass; importjavassist.CtConstructor; importjavassist.CtField; importjavassist.CtMethod; importjavassist.CtNewConstructor; importjavassist.CtNewMethod; importjavassist.Loader; importjavassist.Modifier; importjavassist.bytecode.AccessFlag; /** *Javassist动态编程测试 * *@date2019年03月11日23:00:33 * */ publicclassJavassistTest{ publicstaticvoidmain(String[]args){ try{ test(); }catch(Exceptione){ e.printStackTrace(); } } privatestaticvoidtest()throwsException{ System.out.println("-------------------新增类------------------"); ClassPoolpool=ClassPool.getDefault(); //创建类 CtClassct=pool.makeClass("com.zhi.Person"); //让类实现Cloneable接口 ct.setInterfaces(newCtClass[]{pool.makeInterface("java.lang.Cloneable")}); //添加一个int类型的共有属性 CtFieldfieldId=newCtField(CtClass.intType,"id",ct); fieldId.setModifiers(AccessFlag.PUBLIC); ct.addField(fieldId); //添加一个默认构造器 CtConstructorconstructor1=CtNewConstructor.make("publicPerson(){this.id=1;}",ct); ct.addConstructor(constructor1); //添加方法 CtMethodhelloM=CtNewMethod .make("publicvoidhello(Stringdes){System.out.println(\"执行hello方法,\"+des+\",我的id是\"+this.id);}",ct); ct.addMethod(helloM); //将生成的.class文件保存到磁盘 ct.writeFile(); //加载目标类,可用ct.toClass()或newLoader(pool).loadClass() Class>clazz=ct.toClass(); //Class>clazz=newLoader(pool).loadClass("com.zhi.Person"); //输出类基本信息 System.out.println("包名:"+clazz.getPackageName()); System.out.println("类名:"+clazz.getName()); System.out.println("简要类名:"+clazz.getSimpleName()); System.out.println("限定符:"+Modifier.toString(clazz.getModifiers())); System.out.println("继承类:"+clazz.getSuperclass().getName()); Field[]fields=clazz.getDeclaredFields(); for(Fieldfield:fields){ System.out.println("属性名称:"+field.getName()+",属性类型:"+field.getType()+",限定符:" +Modifier.toString(field.getModifiers())); } //构造一个对象,并执行hello方法 Objectob=clazz.getDeclaredConstructor().newInstance(); clazz.getMethod("hello",String.class).invoke(ob,"张三"); //解冻(执行toClass后会自动冻结) ct.defrost(); System.out.println("-------------------修改类------------------"); //添加一个String类型的私有属性 CtFieldfieldName=newCtField(pool.get(String.class.getName()),"name",ct); fieldName.setModifiers(AccessFlag.PRIVATE); ct.addField(fieldName); //添加带参的构造函数 CtConstructorconstructor2=newCtConstructor(newCtClass[]{pool.get(String.class.getName())},ct); constructor2.setModifiers(Modifier.PUBLIC); constructor2.setBody("{this.name=$1;}"); ct.addConstructor(constructor2); ct.addMethod(CtNewMethod.make("publicvoidsetName(Stringname){this.name=name;}",ct)); ct.addMethod(CtNewMethod.make("publicStringgetName(){returnthis.name;}",ct)); ct.writeFile(); //加载类,若前面已用ct.toClass()进行加载,则这里不能再用ct.toClass()加载,否则会出错,同一个加载不能2次加载同一个类 clazz=newLoader(pool).loadClass("com.zhi.Person"); fields=clazz.getDeclaredFields(); for(Fieldfield:fields){ System.out.println("属性名称:"+field.getName()+",属性类型:"+field.getType()+",限定符:" +Modifier.toString(field.getModifiers())); } ob=clazz.getDeclaredConstructor(String.class).newInstance("马云"); System.out.println("执行getName方法得到的值为:"+clazz.getMethod("getName").invoke(ob)); } }
执行上面代码输出结果为:
-------------------新增类------------------ 包名:com.zhi 类名:com.zhi.Person 简要类名:Person 限定符:public 继承类:java.lang.Object 属性名称:id,属性类型:int,限定符:public 执行hello方法,张三,我的id是1 -------------------修改类------------------ 属性名称:id,属性类型:int,限定符:public 属性名称:name,属性类型:classjava.lang.String,限定符:private 执行getName方法得到的值为:马云
说明:
$0,$1,$2:分别代表this,第一个参数,第二个参数
$r:方法返回值的类型。
$_:方法返回值
依赖包
org.javassist javassist 3.24.1-GA
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。