这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战
再某些特殊的场景下,存在手动创建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
II. 其他
1. 一灰灰Blog: liuyueyi.github.io/hexblog
一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
2. 声明
尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激
- 微博地址: 小灰灰Blog
- QQ: 一灰灰/3302797840
- 微信公众号:一灰灰blog