Javassist 动态生成类

本文介绍如何使用Javassist库动态创建Java类及对象,并实现属性的添加与赋值。通过具体代码示例展示了整个过程。

Javassist是一个开源的分析、编辑和创建Java字节码的类库。

依赖jar包 javassist-3.15.0-GA.jar

package com.dataeye.utils;

import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.Map;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.Loader;
import javassist.Modifier;
import javassist.NotFoundException;


/**
 * 使用 Javassist 动态生成类,也就是创建一个新类。
 * 
 * @author chenfanglin
 * @date 2015年8月3日
 */
public class DynamicCreateObjectUtil {

/**
* 动态创建一个类

* @param className
*            需要创建的java类的名称

* @param fieldMap
*            字段-字段值的属性map,需要添加的属性

* @return

* @throws NotFoundException

* @throws CannotCompileException
* @throws ClassNotFoundException
*/
public static Class createClass(String className,
Map<String, Object> fieldMap) throws NotFoundException,
CannotCompileException, IllegalAccessException,
InstantiationException, ClassNotFoundException {


ClassPool pool = ClassPool.getDefault();// 获取javassist类池
Loader loader = new Loader(pool);
if (pool.getOrNull(className) != null) {
CtClass clas = pool.get(className);
if (clas.isFrozen()) {
// 从pool中拆离这个类
clas.detach();
}
}
CtClass ctClass = pool.makeClass(className);// 创建javassist类
// 为创建的类ctClass添加属性


Iterator it = fieldMap.entrySet().iterator();


while (it.hasNext()) { // 遍历所有的属性


Map.Entry entry = (Map.Entry) it.next();


String fieldName = (String) entry.getKey();


Object fieldValue = entry.getValue();


// 增加属性,这里仅仅是增加属性字段


String fieldType = fieldValue.getClass().getName();


CtField ctField = new CtField(pool.get(fieldType), fieldName,
ctClass);


ctField.setModifiers(Modifier.PUBLIC);


ctClass.addField(ctField);


}
Class c = loader.loadClass(className);
return c;


}


/**
* 给对象属性赋值

* @throws IllegalAccessException
* @throws InstantiationException
* @throws CannotCompileException
*/
public static Object setObjectValue(Class c, Map<String, Object> fieldMap)
throws InstantiationException, IllegalAccessException,
CannotCompileException {
Object newObject = c.newInstance();// 为创建java对象
// 为创建的类newObject属性赋值
Iterator it = fieldMap.entrySet().iterator();
it = fieldMap.entrySet().iterator();


while (it.hasNext()) { // 遍历所有的属性


Map.Entry entry = (Map.Entry) it.next();


String fieldName = (String) entry.getKey();


Object fieldValue = entry.getValue();


// 为属性赋值


setFieldValue(newObject, fieldName, fieldValue);


}


return newObject;
}


/**

* 获取对象属性赋值

* @param dObject

* @param fieldName
*            字段别名

* @return
*/


public static Object getFieldValue(Object dObject, String fieldName) {


Object result = null;


try {


Field fu = dObject.getClass().getDeclaredField(fieldName); // 获取对象的属性域


try {


fu.setAccessible(true); // 设置对象属性域的访问属性


result = fu.get(dObject); // 获取对象属性域的属性值


} catch (IllegalAccessException e) {


e.printStackTrace();


}


} catch (NoSuchFieldException e) {


e.printStackTrace();


}


return result;


}


/**

* 给对象属性赋值

* @param dObject

* @param fieldName

* @param val

* @return
*/


public static Object setFieldValue(Object dObject, String fieldName,
Object val) {


Object result = null;


try {


Field fu = dObject.getClass().getDeclaredField(fieldName); // 获取对象的属性域


try {


fu.setAccessible(true); // 设置对象属性域的访问属性


fu.set(dObject, val); // 设置对象属性域的属性值


result = fu.get(dObject); // 获取对象属性域的属性值


} catch (IllegalAccessException e) {


e.printStackTrace();


}


} catch (NoSuchFieldException e) {


e.printStackTrace();


}


return result;


}


}

动态生成实体可通过以下几种方法实现: ### 使用 javassist 动态生成实体 javassist 是一个开源的分析、编辑和创建 Java 字节码的库,能在运行时动态生成。以下是使用 javassist 动态生成的示例代码: ```java import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class JavassistExample { public static Class<?> makeFunctionImpl() throws Exception { // 1.获取默认池 ClassPool classPool = ClassPool.getDefault(); // 2.创建的内存字节码 CtClass functionImplCt = classPool.makeClass("com.xxx.FunctionImpl"); // 3.继承接口 functionImplCt.addInterface(classPool.getCtClass("com.xxx.FunctionInterface")); // 4.在内存中添加方法实现 // 4.1创建方法实现,并指定所属 CtMethod printMethodImpl = CtMethod.make("public void print(Object o){System.out.println(o);}", functionImplCt); // 4.2添加方法实现 functionImplCt.addMethod(printMethodImpl); // 5.装载到虚拟机 return functionImplCt.toClass(); } public static void main(String[] args) throws Exception { Class<?> clazz = makeFunctionImpl(); Object instance = clazz.getDeclaredConstructor().newInstance(); Method method = clazz.getMethod("print", Object.class); method.invoke(instance, "Hello, World!"); } } ``` 上述代码中,首先获取默认池,接着创建的内存字节码,为添加接口和方法实现,最后将装载到虚拟机。通过反射创建实例并调用方法 [^3]。 ### 基于数据库表结构生成 Java 实体 可以通过 SQL 查询数据库表结构信息,根据这些信息生成对应的 Java 实体代码。示例 SQL 如下: ```sql SELECT concat( '\n/**\n', ' * ', v.column_comment, '\n', ' */\n', 'private ', v.dataType, ' ', v.column_name, ';' ) resultData FROM ( SELECT CASE WHEN ( data_type = 'varchar' OR data_type = 'char' OR data_type = 'text' OR data_type = 'blob' ) THEN 'String' WHEN data_type = 'int' THEN 'int' WHEN data_type = 'bigint' THEN 'Long' WHEN data_type = 'double' THEN 'double' WHEN data_type = 'tinyint' THEN 'Boolean' WHEN data_type = 'datetime' THEN 'Date' END AS dataType, column_name, column_comment FROM information_schema.COLUMNS WHERE table_name = '表名' ) v; ``` 此 SQL 查询会根据数据库表结构生成对应的 Java 实体字段及注释。可以将查询结果拼接成完整的 Java 实体代码 [^4]。 ### 结合 easypoi 和 javassist 实现动态实体用于 Excel 导入导出 基于 easypoi 和 javassist 可实现动态实体生成并进行 Excel 导入导出。通过 javassist 实现动态实体生成,包括字段生成、get/set 方法生成、注解生成,再利用 easypoi 的功能进行 Excel 的导入导出 [^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值