使用javassist动态生成类
2023/6/6大约 2 分钟
Javassist是⼀个开源的分析、编辑和创建Java字节码的类库。是由东京⼯业⼤学的数学和计算机科学 系的 Shigeru Chiba (千叶 滋)所创建的。它已加⼊了开放源代码JBoss 应⽤服务器项⽬,通过使⽤ Javassist对字节码操作为JBoss实现动态"AOP"框架。
引入依赖:
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.29.1-GA</version>
</dependency>使用样例:
// 获取类池
ClassPool pool = ClassPool.getDefault();
// 使用类池制造类 CtClass
CtClass ctClass = pool.makeClass("com.powernode.javassist.Test");
// 创建⽅法 CtMethod
// CtMethod 是 javassist 的类,不是JDK反射机制的类
// ## 分部创建
// 使用构造函数:(1.返回值类型 2.⽅法名 3.形式参数列表 4.所属类)
CtMethod ctMethod = new CtMethod(CtClass.voidType, "execute", new CtClass[]{}, ctClass);
// 设置⽅法的修饰符列表
ctMethod.setModifiers(Modifier.PUBLIC);
// 设置⽅法体
ctMethod.setBody("{System.out.println(\"hello world\");}");
// ## 使用完整的方法代码创建
CtMethod ctMethod = CtMethod.make(methodCode, ctClass);
// methodCode 包含:修饰符列表、返回值类型、方法名、参数表、方法体,是一个完整的符合语法的方法代码。
// 给类添加⽅法
ctClass.addMethod(ctMethod);
// 调⽤⽅法
Class<?> clazz = ctClass.toClass();
Object o = clazz.newInstance();
Method method = clazz.getDeclaredMethod("execute");
method.invoke(o);运行时需要添加如下JVM参数,不然报错:
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/sun.net.util=ALL-UNNAMED

image-20230606194221698
使用 javassist 动态代理生成接口(DAO)实现类:
// 获取类池
ClassPool pool = ClassPool.getDefault();
// 制造类
CtClass ctClass = pool.makeClass("com.powernode.bank.dao.impl.AccountDaoImpl");
// 制造接口
CtClass ctInterface = pool.makeInterface("com.powernode.bank.dao.AccountDao");
// 实现接口
ctClass.addInterface(ctInterface);
// 获取接口中所有的方法(反射机制)
Method[] methods = AccountDao.class.getDeclaredMethods();
// 实现接口中所有的方法:拼接方法的完整实现代码 methodCode
// 反射机制获取返回值类型、方法名、参数表
method.getReturnType().getName();
method.getName();
// 获取参数表
Class<?>[] parameterTypes = method.getParameterTypes();
parameterType.getName(); // 获取参数类型
// 使用 CtMethod 进行实现
CtMethod ctMethod = CtMethod.make(methodCode, ctClass);
// 添加进类
ctClass.addMethod(ctMethod);
// 生成实例对象
Class<?> clazz = ctClass.toClass();
AccountDao accountDao = (AccountDao) clazz.newInstance();