大家好,又见面了,我是你们的朋友全栈君。
概述
常见或常用的几种Bean属性复制工具
- Apache.BeanUtils
- Apache.PropertyUtil
- Spring.BeanUtils
- Cglib.BeanCopier
- MapStruct
- EZMorph
使用场景:Dto与Entity转换
- 普通属性复制
- 个别属性过滤
- 属性类型转换
- 数组或集合拷贝
性能对比
测试在两个简单的Bean之间转换的耗时,执行次数分别为10、100、1k、10k、100k,时间单位为ms。
源码分析
Apache.BeanUtils
org.apache.commons.beanutils
- 通过内省(Introspector)获取源类型的属性信息
- 判断源类型的属性是否可读及目标类型的属性是否可写
- 可读
- 有getter方法
- 可写
- 有setter方法
- 可读
- 进行复制
- 获取属性名
- 获取属性类型
- 进行属性值转类型[自带类型转换器,提供注册自定义转换器接口]
- 赋值
执行过程
- 获取工具实例,调用属性复制方法
- 获取实例方法
- 实例获取的函数是同步的,因为ContextClassLoader的不同,每个线程都会创建一个实例
- 属性复制函数:先是空值的判断,然后通过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。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。