BeanCopier性能对比

本文对比分析了Bean转换工具的性能,包括Apache BeanUtils, PropertyUtils, Spring BeanUtils, Cglib BeanCopier, MapStruct和EZMorph。在性能测试中,观察了不同工具在不同数量对象转换时的耗时。源码分析部分揭示了各工具的工作原理,如BeanUtils依赖内省和类型转换,Cglib BeanCopier使用动态代理生成字节码,而MapStruct支持XML和注解配置。在功能维度上,MapStruct适合复杂转换,Cglib BeanCopier适合简单转换。最后,建议根据性能需求选择合适工具或手动编写getter/setter。" 121493475,9803657,C语言中的数组与指针效率对比,"['C', 'C++', '编程基础']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

常见或常用的几种Bean属性复制工具

  • Apache.BeanUtils
  • Apache.PropertyUtil
  • Spring.BeanUtils
  • Cglib.BeanCopier
  • MapStruct
  • EZMorph

使用场景:Dto与Entity转换

  • 普通属性复制
  • 个别属性过滤
  • 属性类型转换
  • 数组或集合拷贝

性能对比

测试在两个简单的Bean之间转换的耗时,执行次数分别为10、100、1k、10k、100k,时间单位为ms。
BeanCopier性能对比


源码分析

Apache.BeanUtils

org.apache.commons.beanutils

  1. 通过内省(Introspector)获取源类型的属性信息
  2. 判断源类型的属性是否可读及目标类型的属性是否可写
    • 可读
      • 有getter方法
    • 可写
      • 有setter方法
  3. 进行复制
    1. 获取属性名
    2. 获取属性类型
    3. 进行属性值转类型[自带类型转换器,提供注册自定义转换器接口]
    4. 赋值
      在这里插入图片描述

执行过程

  1. 获取工具实例,调用属性复制方法
    在这里插入图片描述
  2. 获取实例方法
    在这里插入图片描述
  3. 实例获取的函数是同步的,因为ContextClassLoader的不同,每个线程都会创建一个实例
    在这里插入图片描述
  4. 属性复制函数:先是空值的判断,然后通过Java内省机制获取属性描述,判断属性是否可读/可写,然后通过反射赋值
    在这里插入图片描述

发现在初始化过程中,BeanUtils实例的获取是“假单例”模式,每个线程拥有一个BeanUtils实例,所以每个线程每次初始化都消耗资源。


Apache.PropertyUtils

org.apache.comons.beanutils

使用内省,操作getter/setter方法。基本流程同Apache.BeanUtils

区别

BeanUtils支持属性类型转换,而PropertyUtils不支持,若有同名不同类型的属性,则会报错。
在这里插入图片描述

BeanUtils自带类型转换器,支持如下类型转换:

  • java.lang.BigDecimal
  • java.lang.BigInteger
  • boolean and java.lang.Boolean
  • byte and java.lang.Byte
  • char and java.lang.Character
  • java.lang.Class
  • double and java.lang.Double
  • float and java.lang.Float
  • int and java.lang.Integer
  • long and java.lang.Long
  • short and java.lang.Short
  • java.lang.String
  • java.sql.Date
  • java.sql.Time
  • java.sql.Timestamp

Springframework.beans.BeanUtils

org.springframework.beans.BeanUtils

Spring的BeanUtils也是通过java内省机制获取getter/setter,然后通过反射调用从而实现属性复制,但区别于Apache的BeanUtils,Spring的BeanUtils为单例模式,不需要重复创建。同时,Spring.BeanUtils支持忽略属性。


Cglib BeanCopier

net.sf.cglib.beans

使用动态代理,生成字节码类,再通过Java反射成Class,调用其copy方法。

执行过程

  • 创建BeanCopier
    在这里插入图片描述
    在这里插入图片描述

    [使用了缓存,该过程也消耗资源,建议全局只初始化一次]
    在这里插入图片描述
    在这里插入图片描述

    通过字节码生成了两个类

    • KeyFactory
    • BeanCopier
  • 调用copy方法。
    在这里插入图片描述
    (支持自定义类型转换器)

    【有convert的情况】
    在这里插入图片描述

    【无convert的情况】
    在这里插入图片描述

    生成的BeanCopier里面直接使用Bean的setter/getter


MapStruct

org.mapstrcut.*

http://mapstruct.org/
支持XML配置和注解配置

使用示例

  • 自定义Mapper类

在这里插入图片描述

  • 编译生成实现类

在这里插入图片描述

  • Bean复制

在这里插入图片描述


EZMorph

性能感人,不做深究。

也是通过反射


功能维度对比

根据属性复制工具的功能维度对工具进行分析,对比如下:

  • Apache.BeanUtils
    在这里插入图片描述
  • Apache.PropertyUtil
    在这里插入图片描述
  • Spring.BeanUtils
    在这里插入图片描述
  • Cglib.BeanCopier
    在这里插入图片描述
  • MapStruct
    在这里插入图片描述
  • EZMorph
    在这里插入图片描述

总结

根据不同工具的性能及功能维度,个人建议当对象转换操作较少或者应用对性能要求较高时,尽量不采用工具,而是手写getter/setter;在不考虑性能的情况下,普通的对象转换可以使用Cglib.BeanCopier,复杂的对象转换使用MapStruct。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值