好吧,这也可以尝试一下。但是,如果有人能解释的话,我需要理解这一点。
更新:
想象一下,您的应用程序必须在运行时从某些外部配置动态创建 Java POJO 实例。可以使用其中一个字节码操作库轻松完成此任务。这篇文章演示了如何使用Javassist库来完成此操作。
假设我们对动态创建的 POJO 应包含的属性具有以下配置:
Map<String, Class<?>> props = new HashMap<String, Class<?>>();
props.put("foo", Integer.class);
props.put("bar", String.class);
让我们编写一个 PojoGenerator,它为给定的类名和映射动态生成一个 Class 对象,其中包含所需的属性:
import java.io.Serializable;
import java.util.Map;
import java.util.Map.Entry;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.NotFoundException;
public class PojoGenerator {
public static Class generate(String className, Map<String, Class<?>> properties) throws NotFoundException,
CannotCompileException {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass(className);
// add this to define a super class to extend
// cc.setSuperclass(resolveCtClass(MySuperClass.class));
// add this to define an interface to implement
cc.addInterface(resolveCtClass(Serializable.class));
for (Entry<String, Class<?>> entry : properties.entrySet()) {
cc.addField(new CtField(resolveCtClass(entry.getValue()), entry.getKey(), cc));
// add getter
cc.addMethod(generateGetter(cc, entry.getKey(), entry.getValue()));
// add setter
cc.addMethod(generateSetter(cc, entry.getKey(), entry.getValue()));
}
return cc.toClass();
}
private static CtMethod generateGetter(CtClass declaringClass, String fieldName, Class fieldClass)
throws CannotCompileException {
String getterName = "get" + fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
StringBuffer sb = new StringBuffer();
sb.append("public ").append(fieldClass.getName()).append(" ")
.append(getterName).append("(){").append("return this.")
.append(fieldName).append(";").append("}");
return CtMethod.make(sb.toString(), declaringClass);
}
private static CtMethod generateSetter(CtClass declaringClass, String fieldName, Class fieldClass)
throws CannotCompileException {
String setterName = "set" + fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
StringBuffer sb = new StringBuffer();
sb.append("public void ").append(setterName).append("(")
.append(fieldClass.getName()).append(" ").append(fieldName)
.append(")").append("{").append("this.").append(fieldName)
.append("=").append(fieldName).append(";").append("}");
return CtMethod.make(sb.toString(), declaringClass);
}
private static CtClass resolveCtClass(Class clazz) throws NotFoundException {
ClassPool pool = ClassPool.getDefault();
return pool.get(clazz.getName());
}
}
就是这样!
使用PojoGenerator非常简单。让我们生成一些POJO,通过反射输出其所有方法,设置然后获取一些属性:
public static void main(String[] args) throws Exception {
Map<String, Class<?>> props = new HashMap<String, Class<?>>();
props.put("foo", Integer.class);
props.put("bar", String.class);
Class<?> clazz = PojoGenerator.generate(
"net.javaforge.blog.javassist.Pojo$Generated", props);
Object obj = clazz.newInstance();
System.out.println("Clazz: " + clazz);
System.out.println("Object: " + obj);
System.out.println("Serializable? " + (obj instanceof Serializable));
for (final Method method : clazz.getDeclaredMethods()) {
System.out.println(method);
}
// set property "bar"
clazz.getMethod("setBar", String.class).invoke(obj, "Hello World!");
// get property "bar"
String result = (String) clazz.getMethod("getBar").invoke(obj);
System.out.println("Value for bar: " + result);
}
执行上述操作将导致以下控制台输出:
Clazz: class net.javaforge.blog.javassist.Pojo$Generated
Object: net.javaforge.blog.javassist.Pojo$Generated@55571e
Serializable? true
public void net.javaforge.blog.javassist.Pojo$Generated.setBar(java.lang.String)
public java.lang.String net.javaforge.blog.javassist.Pojo$Generated.getBar()
public java.lang.Integer net.javaforge.blog.javassist.Pojo$Generated.getFoo()
public void net.javaforge.blog.javassist.Pojo$Generated.setFoo(java.lang.Integer)
Value for bar: Hello World!