Create simple POJO classes (bytecode) at runtime (dynamically)

后端 未结 5 1223
遥遥无期
遥遥无期 2020-11-27 05:24

I\'ve the following scenario..

I am writing some tool that run user-entered query against the database and return the result..

The simplest way is to return

5条回答
  •  误落风尘
    2020-11-27 06:15

    Well This may also given a try. But I need to understand this if anyone can explain.

    UPDATE :

    Imagine your application have to create Java POJO instances dynamically at runtime from some external configuration. This task can be easily done using one of the bytecode manipualtion library. This post demonstrates how this can be done using Javassist library.

    Assume we have following configuration for the properties our dynamically created POJO should contain:

    Map> props = new HashMap>();
    props.put("foo", Integer.class);
    props.put("bar", String.class);
    

    Let’s write a PojoGenerator, that dynamically generates a Class object for the given class name and a map, containing required properties:

    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>  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> 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());
    }
    }
    

    That’s it!

    Using PojoGenerator is quite simple. Let’s generate some POJO, output via reflection all its methods, set and then get some property:

    public static void main(String[] args) throws Exception {
    
    Map> props = new HashMap>();
    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);
    
    }
    

    Executing above will result in the following console output:

    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!
    

提交回复
热议问题