javassist动态生成class
来源:互联网 发布:淘宝国潮模特脖子纹身 编辑:程序博客网 时间:2024/05/29 18:06
什么是javassist?
Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码JBoss应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态"AOP"框架。
关于java字节码的处理,目前有很多工具,如bcel,asm。不过这些都需要直接跟虚拟机指令打交道。如果你不想了解虚拟机指令,可以采用javassist。javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类
联想
由上可知,javassist 可以用来动态生成class文件,并且JVM可以直接加载生成的class文件。具体作用:
设计一个对接系统,通过动态模型的增删改触发业务系统相应服务的调用。模型增删改方法动态发布为WebService服务。WebService服务采用CXF发布,动态类生成采用Javassist。由于WebService服务类需要添加WebService相关注解。
实战演练
从0开始实战,首先我们认识最初级的由javassist生成class类并且修改保存
package com.bsoft.javassis;import java.io.FileOutputStream;import java.io.IOException;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.CtNewMethod;import javassist.NotFoundException;public class TestJavassis {/** * @param args * @author yuzg * update time 2017-06-20 */public static void main(String[] args) {// TODO Auto-generated method stub/** * ClassPool是缓存CtClass对象的容器,所有的CtClass对象都在ClassPool中。 * 所以,CtClass对象很多时,ClassPool会消耗很大的内存,为了避免内存的消耗 * ,创建ClassPool对象时可以使用单例模式, * 或者对于CtClass对象,调用detach方法将其从ClassPool中移除 * 在ClassPool源码中getDefault 是单例模式生成 * * public static synchronized ClassPool getDefault() { if (defaultPool == null) { defaultPool = new ClassPool(null); defaultPool.appendSystemPath(); } return defaultPool; } */ClassPool classpool =ClassPool.getDefault();//创建类名CtClass ctClass = classpool.makeClass("com.bsoft.esb.IEsbInvoker1");//ctClass.stopPruning(true);try {//添加属性 ctClass.addField(CtField.make("private int age;", ctClass)); //添加setAge方法 ctClass.addMethod(CtMethod.make("public void setAge(int age){this.age = age;}", ctClass)); ctClass.addMethod(CtMethod.make("public int getAge(){return this.age;}", ctClass));byte[] byteArray = ctClass.toBytecode(); FileOutputStream output = new FileOutputStream("D:\\IEsbInvoker1.class"); output.write(byteArray); output.close(); /*** * 如果下面的判断和解冻方法不加会报错 * java.lang.RuntimeException: com.bsoft.esb.IEsbInvoker1 class is frozen * 原因解释如下: * 当CtClass对象通过writeFile()、toClass()、toBytecode()转化为Class后, * Javassist冻结了CtClass对象,因此,JVM不允许再次加载Class文件,所以不允许对其修改。 */ if(ctClass.isFrozen()){ctClass.defrost();} ctClass = classpool.get("com.bsoft.esb.IEsbInvoker1");System.out.println(ctClass);CtField param = new CtField(classpool.get("java.lang.String"), "name", ctClass); ctClass.addField(CtField.make("private java.lang.String sex;", ctClass)); ctClass.addField(CtField.make("private java.lang.String name;", ctClass)); ctClass.addMethod(CtNewMethod.setter("setName", param)); ctClass.addMethod(CtNewMethod.getter("getName", param)); // // 添加无参的构造体 // CtConstructor cons = new CtConstructor(new CtClass[] {}, ctClass); // cons.setBody("{name = \"Brant\";}"); // ctClass.addConstructor(cons); // 添加有参的构造体 CtConstructor cons = new CtConstructor(new CtClass[] {classpool.get("java.lang.String")}, ctClass); cons.setBody("{$0.name = $1;}"); ctClass.addConstructor(cons); byteArray = ctClass.toBytecode(); output = new FileOutputStream("D:\\IEsbInvoker1.class"); output.write(byteArray); output.close(); //ctClass转class后创建对象 Object o =ctClass.toClass().newInstance(); //这样写会报错:java.lang.ClassNotFoundException: com.bsoft.esb.IEsbInvoker1 /*** * 此时应该还在pool中 */// Class.forName("com.bsoft.esb.IEsbInvoker1").newInstance(); //获取方法 Method methodSet = o.getClass().getMethod("setName", new Class[] {String.class}); //反射原理 methodSet.invoke(o, "Alen"); Method getter = o.getClass().getMethod("getName"); System.out.println("name:"+getter.invoke(o, null));} catch (NotFoundException e) {System.out.println(e.getMessage());// TODO Auto-generated catch blocke.printStackTrace();}catch (CannotCompileException e) {System.out.println(e.getMessage());e.printStackTrace();}catch (IOException e) {e.printStackTrace();}catch (Exception e) {e.printStackTrace();}}
$0, $1, $2, ... 代表的含义:
$0代表的是this,$1代表方法参数的第一个参数、$2代表方法参数的第二个参数,以此类推,$N代表是方法参数的第N个。例如:
setName(String Name){ $0.name=$1;}相当于 this.name=Name;
首次保存生成的class文件:
package com.bsoft.esb;public class IEsbInvoker1{ private int age; public void setAge(int paramInt) { this.age = paramInt; } public int getAge() { return this.age; }}
输出:
name:Alen
一个class 文件就生成好了。并且通过java反射机制可以明显看出,和jvm主动调用class类中的方法并无两样。稍后上传jar包资源文件
javassist.jar下载路径:点击下载javassist
阅读全文
1 0
- javassist动态生成class
- Javassist 动态生成类
- javassist 动态生成WebService
- webx—javassist动态创建class文件
- Javassist生成class(生成类,方法,字段,注解)
- 使用javassist框架进行动态的更改Class类
- Android动态编译技术:Plugin Transform Javassist操作Class文件
- JAVAssist---动态修改注解
- JAVAssist---动态修改注解
- Javassist实现动态代理
- Android Gradle高级用法,动态编译技术:Plugin Transform Javassist操作Class文件
- 使用javassist修改class文件
- Myeclipse中的使用javassist修改时class文件时生成的class文件在项目的根目录下。
- 利用Java反射机制和Javassist实现Java对象及其属性的动态创建生成
- 利用Java反射机制和Javassist实现Java对象及其属性的动态创建生成
- 使用javassist生成新类
- javassist生成的对象回收
- 使用javassist生成新类
- 欢迎使用CSDN-markdown编辑器
- 屏幕适配学习
- bzoj3555 [Ctsc2014]企鹅QQ
- 删除字符串中的*号
- 欢迎使用CSDN-markdown编辑器
- javassist动态生成class
- InheritableThreadLocal-- 特殊的ThreadLocal
- 关系型数据库和非关系数据库
- DM368开发 -- Bootloader 开发(转毕设)
- 复制文本到系统, textview 复制内容
- 重写equals方法和hashcode(集合需要重写)
- [C++ Primer CH01]第1章 开始
- Matlab 标定工具箱使用教程
- 获取线程标识函数gettid和pthread_self的区别