再某些特殊的场景下,存在手动创建java类的case,比如我有个需求,希望根据简单的Map对象,来生成一个对应的Java bean,可以怎么整?
针对这个而典型的场景,先考虑是否有现成可用的开源工具类来实现,比如我们经常接触到cglib,它可以动态生成代理对象,那么生成Java Bean也没有什么问题
接下来我们看一下使用cglib来创建bean的方式
1. cglib动态创建bean
首先添加cglib的依赖
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>[3.3.0,)</version> </dependency> 复制代码
接下来的bean创建,主要是借助 BeanGenereator
+ BeanMap
来实现
创建Java Bean对象,主要借助 BeanGenerator来完成,需要根据传入的Map中value的类型,来定义生成对象的属性类型
private Object instanceObject(Map<String, Object> map) { Map<String, Class> properties = new HashMap<>(map.size()); for (Map.Entry<String, Object> entry : map.entrySet()) { properties.put(entry.getKey(), entry.getValue().getClass()); } // 根据属性生成实体bean return generateBean(properties); } private Object generateBean(Map<String, Class> propertyMap) { //根据一组属性名和属性值的类型,动态创建Bean对象 BeanGenerator generator = new BeanGenerator(); Set keySet = propertyMap.keySet(); for (Iterator i = keySet.iterator(); i.hasNext(); ) { String key = (String) i.next(); generator.addProperty(key, (Class) propertyMap.get(key)); } return generator.create(); //创建Bean } 复制代码
上面这两个方法,就实现了根据Map来创建java bean对象;此时bean对象已经生成,成员属性也都指定了,但是还没有初始化value
接下来的value设置,则利用BeanMap来处理
private void initObject(Map<String, Object> map) { //用实体Bean创建BeanMap,用于获取和设置value // 这个object就是上面生成的实体类 beanMap = BeanMap.create(this.object); for (Map.Entry<String, Object> entry : map.entrySet()) { beanMap.put(entry.getKey(), entry.getValue()); } } 复制代码
如果我们希望获取这个object中的成员值,同样也是借助BeanMap来实现(因为新生成的JavaBean并没有赋予相应的get/set方法)
public Object getValue(String key) { return beanMap.get(key); } 复制代码
接下来将上面的代码封装一下,并给一个测试
public class CglibBean { private Object object = null; private BeanMap beanMap = null; public CglibBean(Map<String, Object> map) { this.object = instanceObject(map); initObject(map); } private Object instanceObject(Map<String, Object> map) { Map<String, Class> properties = new HashMap<>(map.size()); for (Map.Entry<String, Object> entry : map.entrySet()) { properties.put(entry.getKey(), entry.getValue().getClass()); } // 根据属性生成实体bean return generateBean(properties); } private void initObject(Map<String, Object> map) { //用实体Bean创建BeanMap,用于获取和设置value beanMap = BeanMap.create(this.object); for (Map.Entry<String, Object> entry : map.entrySet()) { beanMap.put(entry.getKey(), entry.getValue()); } } /** * 得到该实体bean对象 * * @return */ public Object getObject() { return this.object; } public Object getValue(String key) { return beanMap.get(key); } private Object generateBean(Map<String, Class> propertyMap) { //根据一组属性名和属性值的类型,动态创建Bean对象 BeanGenerator generator = new BeanGenerator(); Set keySet = propertyMap.keySet(); for (Iterator i = keySet.iterator(); i.hasNext(); ) { String key = (String) i.next(); generator.addProperty(key, (Class) propertyMap.get(key)); } return generator.create(); //创建Bean } public static void main(String[] args) throws IllegalAccessException { // 设置类成员属性 HashMap<String, Object> map = new HashMap<>(); map.put("id", 123); map.put("name", "hello"); map.put("now", new Date()); CglibBean bean = new CglibBean(map); // 获得bean的实体 Object object = bean.getObject(); Field[] fields = object.getClass().getDeclaredFields(); for (Field f: fields) { f.setAccessible(true); System.out.println("field: " + f.getName() + " = " + f.get(object)); } System.out.println("----------------"); System.out.println(bean.getValue("id")); } } 复制代码
接下来我们看一下测试输出
field: $cglib_prop_now = Fri Aug 20 16:29:00 CST 2021 field: $cglib_prop_name = hello field: $cglib_prop_id = 123 ---------------- 123