你还在用 BeanUtils?试试 MapStruct,优雅的对象转换解决方案!
第一次看到 MapStruct
的时候, 我个人非常的开心。因为其跟我内心里面的想法不谋而合。
1 MapStruct 是什么?
1.1 JavaBean 的困扰
对于代码中
之间的转换, 一直是困扰我很久的事情。JavaBean
在开发的时候我看到业务代码之间有很多的
之间的相互转化, 非常的影响观感, 却又不得不存在。我后来想的一个办法就是通过反射, 或者自己写很多的转换器。JavaBean
第一种通过反射的方法确实比较方便, 但是现在无论是 BeanUtils
, BeanCopier
等在使用反射的时候都会影响到性能。虽然我们可以进行反射信息的缓存来提高性能。
但是像这种的话, 需要类型和名称都一样才会进行映射, 有很多时候, 由于不同的团队之间使用的名词不一样, 还是需要很多的手动 set/get 等功能。
第二种的话就是会很浪费时间, 而且在添加新的字段的时候也要进行方法的修改。不过, 由于不需要进行反射, 其性能是很高的。
1.2 MapStruct
带来的改变
MapSturct
是一个生成类型安全, 高性能且无依赖的 JavaBean 映射代码的注解处理器(annotation processor)。
抓一下重点:
注解处理器
可以生成
JavaBean
之间那的映射代码类型安全, 高性能, 无依赖性
从字面的理解, 我们可以知道, 该工具可以帮我们实现
之间的转换, 通过注解的方式。JavaBean
同时, 作为一个工具类,相比于手写, 其应该具有便捷, 不容易出错的特点。
2 MapStruct
入门
入门很简单。我是基于 Maven
来进行项目 jar 包管理的。
2.1 引入依赖
<properties><org.mapstruct.version>1.3.0.Final</org.mapstruct.version>
</properties><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-jdk8</artifactId><version>${org.mapstruct.version}</version>
</dependency><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>${org.mapstruct.version}</version>
</dependency>
2.2 创建entity和dto对象
该类是从 github 某个订单系统里面拿下来的部分。
@Data
public class Order {/***订单id*/private Long id;/*** 订单编号*/private String orderSn;/*** 收货人姓名/号码*/private String receiverKeyword;/*** 订单状态:0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单*/private Integer status;/*** 订单类型:0->正常订单;1->秒杀订单*/private Integer orderType;/*** 订单来源:0->PC订单;1->app订单*/private Integer sourceType;
}
对应的查询参数
@Data
public class OrderQueryParam {/*** 订单编号*/private String orderSn;/*** 收货人姓名/号码*/private String receiverKeyword;/*** 订单状态:0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单*/private Integer status;/*** 订单类型:0->正常订单;1->秒杀订单*/private Integer orderType;/*** 订单来源:0->PC订单;1->app订单*/private Integer sourceType;}
2.3 写 Mapper
Mapper
即映射器, 一般来说就是写 xxxMapper
接口。
当然, 不一定是以 Mapper
结尾的。只是官方是这么写的。在本入门例子中,对应的接口如下
import com.homejim.mapstruct.dto.OrderQueryParam;
import com.homejim.mapstruct.entity.Order;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;@Mapper
public interface OrderMapper {OrderQueryParam entity2queryParam(Order order);}
简单的映射(字段和类型都匹配), 只有一个要求, 在接口上写 @Mapper
注解即可。
然后方法上, 入参对应要被转化的对象, 返回值对应转化后的对象, 方法名称可任意。
2.4 测试
写一个测试类测试一下。
@Test
public void entity2queryParam() {Order order = new Order();order.setId(12345L);order.setOrderSn("orderSn");order.setOrderType(0);order.setReceiverKeyword("keyword");order.setSourceType(1);order.setStatus(2);OrderMapper mapper = Mappers.getMapper(OrderMapper.class);OrderQueryParam orderQueryParam = mapper.entity2queryParam(order);assertEquals(orderQueryParam.getOrderSn(), order.getOrderSn());assertEquals(orderQueryParam.getOrderType(), order.getOrderType());assertEquals(orderQueryParam.getReceiverKeyword(), order.getReceiverKeyword());assertEquals(orderQueryParam.getSourceType(), order.getSourceType());assertEquals(orderQueryParam.getStatus(), order.getStatus());}
测试通过, 没有任何的问题。
3 MapStruct 分析
上面中, 我写了3个步骤来实现了从 Order
到 OrderQueryParam
的转换。
那么, 作为一个注解处理器, 通过MapStruct
生成的代码具有怎么样的优势呢?
3.1 高性能
这是相对反射来说的, 反射需要去读取字节码的内容, 花销会比较大。学反射看《Java反射看这篇绝对会了》这篇够了!关注公众号互联网架构师可以Java技术干货教程。
而通过 MapStruct
来生成的代码, 其类似于人手写。速度上可以得到保证。
前面例子中生成的代码可以在编译后看到。在 target/generated-sources/annotations 里可以看到。
对应的代码
@Generated(value = "org.mapstruct.ap.MappingProcessor",date = "2019-08-02T00:29:49+0800",comments = "version: 1.3.0.Final, compiler: javac, environment: Java 11.0.2 (Oracle Corporation)"
)
public class OrderMapperImpl implements OrderMapper {@Overridepublic OrderQueryParam entity2queryParam(Order order) {if ( order == null ) {return null;}OrderQueryParam orderQueryParam = new OrderQueryParam();orderQueryParam.setOrderSn( order.getOrderSn() );orderQueryParam.setReceiverKeyword( order.getReceiverKeyword() );orderQueryParam.setStatus( order.getStatus() );orderQueryParam.setOrderType( order.getOrderType() );orderQueryParam.setSourceType( order.getSourceType() );return orderQueryParam;}
}
可以看到其生成了一个实现类, 而代码也类似于我们手写, 通俗易懂。
3.2 易于 debug
在我们生成的代码中, 我们可以轻易的进行 debug。
在使用反射的时候, 如果出现了问题, 很多时候是很难找到是什么原因的。
3.3 使用相对简单
如果是完全映射的, 使用起来肯定没有反射简单。用类似 BeanUtils
这些工具一条语句就搞定了。但是,如果需要进行特殊的匹配(特殊类型转换, 多对一转换等), 其相对来说也是比较简单的。
基本上, 使用的时候, 我们只需要声明一个接口, 接口下写对应的方法, 就可以使用了。当然, 如果有特殊情况, 是需要额外处理的。
3.4 代码独立
生成的代码是对立的, 没有运行时的依赖。
作者:阿进的写字台
出处:https://www.cnblogs.com/homejim/
关注微信公众号:互联网架构师,在后台回复:2T,可以获取我整理的教程,都是干货。
猜你喜欢
1、GitHub 标星 3.2w!史上最全技术人员面试手册!FackBoo发起和总结
2、如何才能成为优秀的架构师?
3、从零开始搭建创业公司后台技术栈
4、程序员一般可以从什么平台接私活?
5、37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...
6、滴滴业务中台构建实践,首次曝光
7、不认命,从10年流水线工人,到谷歌上班的程序媛,一位湖南妹子的励志故事
8、15张图看懂瞎忙和高效的区别
9、2T架构师学习资料干货分享
你还在用 BeanUtils?试试 MapStruct,优雅的对象转换解决方案!相关推荐
- MapStruct解决数据传输对象转换的繁琐
每层有自己的数据传输对象,当数据流程到该层由需要将数据转成符合要求的格式,比如:当数据由应用层流转到服务层则需要将数据转成DTO格式,当数据由服务层流向持久层则需要将数据转成Entity格式数据 下边 ...
- 芋道 Spring Boot 对象转换 MapStruct 入门
点击上方"芋道源码",选择"设为星标" 做积极的人,而不是积极废人! 源码精品专栏 原创 | Java 2020 超神之路,很肝~ 中文详细注释的开源项目 RP ...
- Java对象转换方案分析与mapstruct实践
简介: 随着系统模块分层不断细化,在Java日常开发中不可避免地涉及到各种对象的转换,如:DO.DTO.VO等等,编写映射转换代码是一个繁琐重复且还易错的工作,一个好的工具辅助,减轻了工作量.提升开发 ...
- 一个优雅的占位图解决方案。适用于 UITableView 和 UICollectionView。
FMListPlaceholder 项目地址:https://github.com/yfming93/FMListPlaceholder 一个优雅的占位图解决方案.适用于 UITableView 和 ...
- 生僻字用计算机怎么弹数字,原来Windows自带输入法还能这么用?生僻字、数字转换,超好用...
原标题:原来Windows自带输入法还能这么用?生僻字.数字转换,超好用 在使用电脑的时候,我们很多时候会选择安卓一些输入法,但是有时候会出现很多的弹窗广告,这是比较麻烦的,其实Windows有自带的 ...
- 还在用 BeanUtils来做对象转换吗?快试试 MapStruct吧
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:阿进的写字台 https://www.cnblogs ...
- 还在使用BeanUtils.copyProperties()? 来看看MapStruct,强大五倍
来杭州了,2021年4月26日入职新公司,接触的第一个项目就使用到了这个技术,挺新颖的,也挺好用的,效率也高,见猎心喜,遂有此博客 简介 MapStruct是满足JSR269规范的一个Java注解处理 ...
- 对象拷贝之Apache BeanUtils、Spring的BeanUtils、Mapstruct、BeanCopier、PropertieyUtils对比(深拷贝)
大多时候时候使用的是Apache或Spring``BeanUtils,今天,我们来看一下一个更高效的属性拷贝方式:BeanCopier. https://github.com/cglib/cglib ...
- 实体拷贝工具大汇总,你还在用BeanUtils? 赶紧来学一学吧
我们在项目当中,经常会遇到实体拷贝的情况,必须把DO拷贝到BO, BO拷贝到VO等等,这个时候,如果我们还是单纯的使用get/set 会发现,代码可能会变得非常的臃肿,但不可置疑的是get/set不会 ...
- 读取Excel还用POI?试试这款开源工具
点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 作者 | 优雅先生 来源 | my.oschina.net/feichexia/blog/1 ...
最新文章
- css菜单缓慢滑动_如何使用HTML,CSS和JavaScript构建滑动菜单栏
- 图像处理之基于阈值模糊
- 数据之路 Day8 Matplotlib包
- STM32 基础系列教程 41 – SDMMC
- 将输出的数据按照表格的形式进行输出
- [深度学习基础] 深度学习基础及数学原理
- Java:数值-字符串转换(String转Double)
- flutter能开发游戏吗_Steam上架游戏开发软件,不用代码也能制作游戏,而且还是免费的...
- 程序员过关斩将--互联网人必备知识cookie和session认证
- Postman用法简介-Http请求模拟工具
- SpringCloud学习笔记008---杂七杂八002_spring 注解@Value详解_@Value(quot;#{}quot;)与@Value(quot;${}quot;)的区别
- python AES对称加密文件、解密文件
- ENSP之STP协议基本配置教程
- 生如夏花之灿烂,死如秋叶之静美
- matlab 分水岭法,分水岭算法Matlab实现——三种方法 | 学步园
- 警告: 忽略额外的图例条目
- windows7软件显示问号乱码问题
- php开发和java的区别
- countByKey()案例和foreach(func)案例_大数据培训课程
- 从LiveJournal后台发展看大规模网站性能优化方法 于敦德 2006-3-16
热门文章
- 2019年2月22日 深入理解计算机系统(CS:APP)第一章读书笔记
- linux网络测试(必会)
- 互联网创业的准备——数据库:硬盘iops、mysql
- 【例9.3】求最长不下降序列
- 就地升级Lync Server 到Skype for Business Server
- 第3/24周 区_SQL Server中管理空间的基本单位
- 大数据时代:如何节省存储成本
- 在 Mac 上的 Keynote 讲演中如何自动替换文本?
- SwitchResX Mac屏幕分辨率调整工具
- Screaming Frog SEO Spider for Mac(网络爬虫软件)v16.0