Java BeanMap实现Bean与Map的相互转换

 更新时间:2022年11月20日 10:16:24   作者:氵奄不死的鱼  
这篇文章主要介绍了利用BeanMap进行对象与Map的相互转换,通过net.sf.cglib.beans.BeanMap类中的方法来转换,效率极高,本文给大家分享实现代码,感兴趣的朋友一起看看吧

net.sf.cglib.beans.BeanMap用法

bean转Map

@Data
public class Student {
    private int id;
    private String name;
    private Integer age;
}
    Student student = new Student();
    BeanMap beanMap = BeanMap.create(student);

此时的beanMap就是一个map类型

但是对于直接生成的beanMap无法添加key,也无法删除key(会报错),并且修改值会直接影响到student这个对象。

如果有这个需求可以再进一步转换为HashMap(如果没这个需要,就不要再转换,避免不必要的性能浪费)

HashMap map = new HashMap();
map.putAll(beanMap);

map转Bean

普通Map转转换成bean

        HashMap map = new HashMap();
        map.put("name","hello world");   
        Student student = new Student();
        BeanMap beanMap = BeanMap.create(student);
        beanMap.putAll(map);

利用了修改beanMap会影响bean的特性,将map put到beanMap完成转换.

beanMap转成对应的bean

public static <T> T beanMapToBean(BeanMap beanMap) {
        if (beanMap == null) {
            throw new DataStreamException("bean.can.not.be.null");
        }
        return (T) beanMap.getBean();
    }

直接调用getBean方法就可以获取beanMap对应的bean

beanMap实现以及高性能的原因

先看beanMap

public abstract class BeanMap implements Map 

继承自Map接口,实现了contains,remove,put,get等操作

    public Object remove(Object key) {
        throw new UnsupportedOperationException();
    }

但是remove会抛出UnsupportedOperationException

BeanMap.create()方法通过asm动态生成字节码创建一个beanMap

那么我们来看看创建出来的beanMap的字节码文件

import java.math.BigDecimal;
import java.util.Date;
import java.util.Set;
import net.sf.cglib.beans.BeanMap;
import net.sf.cglib.beans.FixedKeySet;
public class Student$$BeanMapByCGLIB$$54bf0fe9 extends BeanMap {
    private static FixedKeySet keys;
    private static final Class CGLIB$load_class$java$2Eutil$2ESet;
    private static final Class CGLIB$load_class$java$2Elang$2EInteger;
    private static final Class CGLIB$load_class$java$2Elang$2EString;
    private static final Class CGLIB$load_class$java$2Emath$2EBigDecimal;
    private static final Class CGLIB$load_class$java$2Eutil$2EDate;
    public Student$$BeanMapByCGLIB$$54bf0fe9() {
    }
    public BeanMap newInstance(Object var1) {
        return new Student$$BeanMapByCGLIB$$54bf0fe9(var1);
    }
    public Student$$BeanMapByCGLIB$$54bf0fe9(Object var1) {
        super(var1);
    }
    public Object get(Object var1, Object var2) {
        Student var10000 = (Student)var1;
        String var10001 = (String)var2;
        switch(((String)var2).hashCode()) {
        case -600094315:
            if (var10001.equals("friends")) {
                return var10000.getFriends();
            }
            break;
        case 3355:
            if (var10001.equals("id")) {
                return new Integer(var10000.getId());
            }
            break;
        case 96511:
            if (var10001.equals("age")) {
                return var10000.getAge();
            }
            break;
        case 3373707:
            if (var10001.equals("name")) {
                return var10000.getName();
            }
            break;
        case 104079552:
            if (var10001.equals("money")) {
                return var10000.getMoney();
            }
            break;
        case 1069376125:
            if (var10001.equals("birthday")) {
                return var10000.getBirthday();
            }
        }
        return null;
    }
    public Object put(Object var1, Object var2, Object var3) {
        Student var10000 = (Student)var1;
        String var10001 = (String)var2;
        switch(((String)var2).hashCode()) {
        case -600094315:
            if (var10001.equals("friends")) {
                Set var7 = var10000.getFriends();
                var10000.setFriends((Set)var3);
                return var7;
            }
            break;
        case 3355:
            if (var10001.equals("id")) {
                Integer var10003 = new Integer(var10000.getId());
                var10000.setId(((Number)var3).intValue());
                return var10003;
            }
            break;
        case 96511:
            if (var10001.equals("age")) {
                Integer var6 = var10000.getAge();
                var10000.setAge((Integer)var3);
                return var6;
            }
            break;
        case 3373707:
            if (var10001.equals("name")) {
                String var5 = var10000.getName();
                var10000.setName((String)var3);
                return var5;
            }
            break;
        case 104079552:
            if (var10001.equals("money")) {
                BigDecimal var4 = var10000.getMoney();
                var10000.setMoney((BigDecimal)var3);
                return var4;
            }
            break;
        case 1069376125:
            if (var10001.equals("birthday")) {
                Date var10002 = var10000.getBirthday();
                var10000.setBirthday((Date)var3);
                return var10002;
            }
        }
        return null;
    }
    static {
        CGLIB$STATICHOOK1();
        keys = new FixedKeySet(new String[]{"birthday", "money", "name", "id", "age", "friends"});
    }
    static void CGLIB$STATICHOOK1() {
        CGLIB$load_class$java$2Eutil$2ESet = Class.forName("java.util.Set");
        CGLIB$load_class$java$2Elang$2EInteger = Class.forName("java.lang.Integer");
        CGLIB$load_class$java$2Elang$2EString = Class.forName("java.lang.String");
        CGLIB$load_class$java$2Emath$2EBigDecimal = Class.forName("java.math.BigDecimal");
        CGLIB$load_class$java$2Eutil$2EDate = Class.forName("java.util.Date");
    }
    public Set keySet() {
        return keys;
    }
    public Class getPropertyType(String var1) {
        switch(var1.hashCode()) {
        case -600094315:
            if (var1.equals("friends")) {
                return CGLIB$load_class$java$2Eutil$2ESet;
            }
            break;
        case 3355:
            if (var1.equals("id")) {
                return Integer.TYPE;
            }
            break;
        case 96511:
            if (var1.equals("age")) {
                return CGLIB$load_class$java$2Elang$2EInteger;
            }
            break;
        case 3373707:
            if (var1.equals("name")) {
                return CGLIB$load_class$java$2Elang$2EString;
            }
            break;
        case 104079552:
            if (var1.equals("money")) {
                return CGLIB$load_class$java$2Emath$2EBigDecimal;
            }
            break;
        case 1069376125:
            if (var1.equals("birthday")) {
                return CGLIB$load_class$java$2Eutil$2EDate;
            }
        }
        return null;
    }
}

这个生成的类继承自BeanMap,在构造时传进来bean实例,并且根据bean的属性创建对应的get/put方法

可以看出来在执行get和put时都是根据属性名称找到对应bean实例的set/get方法进行处理。也因此beanMap和对应实例会相互影响

还具备getPropertyType获取字段类型的功能

在bean转map过程中除了生成这个动态class之外(生成之后会缓存,对于同一类型的bean,不会重复创建),整个过程没有真正复制对象变成map(避免的内存的浪费),也没有通过效率较慢的反射去操作bean实例。因此BeanMap性能是比较不错的

到此这篇关于Java BeanMap实现Bean与Map的相互转换的文章就介绍到这了,更多相关Bean与Map的相互转换内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • javaweb 实现文件下载的方法及实例代码

    javaweb 实现文件下载的方法及实例代码

    这篇文章主要介绍了javaweb 实现文件下载的方法的相关资料,这里提供了实现代码,需要的朋友可以参考下
    2016-11-11
  • Spring Boot集成JavaMailSender发送邮件功能的实现

    Spring Boot集成JavaMailSender发送邮件功能的实现

    spring提供了发送邮件的接口JavaMailSender,通过JavaMailSender可以实现后端发送邮件,下面这篇文章主要给大家介绍了关于Spring Boot集成JavaMailSender发送邮件功能的相关资料,需要的朋友可以参考下
    2022-05-05
  • java异步上传图片示例

    java异步上传图片示例

    这篇文章主要介绍了java异步上传图片示例,需要的朋友可以参考下
    2014-02-02
  • springboot使用shiro-整合redis作为缓存的操作

    springboot使用shiro-整合redis作为缓存的操作

    这篇文章主要介绍了springboot使用shiro-整合redis作为缓存的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Spring之从桥接方法到JVM方法调用解读

    Spring之从桥接方法到JVM方法调用解读

    这篇文章主要介绍了Spring之从桥接方法到JVM方法调用解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • Java多线程中的Executor详解

    Java多线程中的Executor详解

    这篇文章主要介绍了Java多线程中的Executor详解,该接口提供了一种将任务提交与如何运行每个任务的机制(包括线程使用、调度等细节)解耦的方法,它通常使用预先创建线程而不是创建线程,需要的朋友可以参考下
    2023-12-12
  • m1 Mac设置多jdk版本并动态切换的实现

    m1 Mac设置多jdk版本并动态切换的实现

    本文主要介绍 Mac 下如何安装 JDK 并且多版本如何切换,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • Java中Map集合(接口)的基本方法程序演示

    Java中Map集合(接口)的基本方法程序演示

    这篇文章主要为大家详细介绍了Java中Map集合的基本方法程序演示,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • 巧妙的利用Mongodb做地理空间查询

    巧妙的利用Mongodb做地理空间查询

    本篇文章将会以Mongodb为数据库,讲述如何在数据库层级进行定位查询。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • java poi导出图片到excel示例代码

    java poi导出图片到excel示例代码

    这篇文章主要介绍java poi如何导出图片到excel,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03

最新评论