基于Java字节码技术,如ASM、Javassist,前者偏底层、构建复杂,但性能相对较高;后者提供了友好的API接口方法,优雅简单,但性能稍弱。
本文基于Javassist,初探性以创建一个简单的类、里面创建一个普通属性以及一个静态属性为示例:
引入Maven依赖
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.30.2-GA</version>
</dependency>
示例代码
import com.google.gson.Gson;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtNewMethod;
public class DynamicPropertyExampleJavassist {
public static void main(String[] args) throws Exception {
// 创建一个类池
ClassPool pool = ClassPool.getDefault();
// 创建一个新的类(完全限定的类型)
CtClass cc = pool.makeClass("com.mc.User");
// 添加接口
cc.setInterfaces(new CtClass[] {pool.makeInterface("java.io.Serializable")});
// 添加静态属性并赋值
cc.addField( CtField.make("private static final long serialVersionUID = 1L;", cc));
// 添加新的属性
CtField newField = CtField.make("private String username;", cc);
cc.addField(newField);
// 添加属性username的 Getter和Setter方法
cc.addMethod(CtNewMethod.setter("setUsername", newField));
cc.addMethod(CtNewMethod.getter("getUsername", newField));
// 将CtClass转换为Class对象
Class<?> clazz = cc.toClass();
System.out.println("clazz: " + clazz.getName());
System.out.println("package: " + clazz.getPackage());
// 反射创建一个对象
Object obj = clazz.newInstance();
System.out.println("obj: " + obj);
// 使用Setter方法设置新属性值
clazz.getMethod("setUsername", String.class).invoke(obj, "张三");
// 使用Getter方法获取新属性值并打印
System.out.println("New Property: " + clazz.getMethod("getUsername").invoke(obj));
// 转为JSON字符串
System.err.println(new Gson().toJson(obj));
}
}
结果: