还在用 BeanUtils来做对象转换吗?快试试 MapStruct吧
点击上方蓝色“方志朋”,选择“设为星标”
回复“666”获取独家整理的学习资料!
作者:阿进的写字台
https://www.cnblogs.com/homejim/
第一次看到 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 高性能
这是相对反射来说的, 反射需要去读取字节码的内容, 花销会比较大。而通过 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 代码独立
生成的代码是对立的, 没有运行时的依赖。
热门内容:
别说,Cerebro还真好用!老板再也不用担心ES集群了
用了3年Apollo,这次我选择了Nacos,原因不多说了
为什么强烈推荐 Java 程序员使用 Google Guava 编程!
最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
明天见(。・ω・。)ノ♡
还在用 BeanUtils来做对象转换吗?快试试 MapStruct吧相关推荐
- Java对象转换方案分析与mapstruct实践
简介: 随着系统模块分层不断细化,在Java日常开发中不可避免地涉及到各种对象的转换,如:DO.DTO.VO等等,编写映射转换代码是一个繁琐重复且还易错的工作,一个好的工具辅助,减轻了工作量.提升开发 ...
- java dozer map转对象_对象转换利器之Dozer
在Java的世界中,经常会涉及到需要在2个对象中进行转换,比如说: 调用SOAP Web服务,需要把自己的Domain对象转换为Soap服务的Jaxb对象请求, 在分层级SOA架构中,2个层级之间Do ...
- 芋道 Spring Boot 对象转换 MapStruct 入门
点击上方"芋道源码",选择"设为星标" 做积极的人,而不是积极废人! 源码精品专栏 原创 | Java 2020 超神之路,很肝~ 中文详细注释的开源项目 RP ...
- android 中XML和对象转换利器Xstream的使用
XStream框架: 虽说pull dom dom4j等优秀的xml解析工具使用非常广泛,但对于复杂庞大的数据交互来说,使用它们无疑让你倍加痛苦,你可能大部分精力都放在无聊繁琐的解析和拼装上,如果接口 ...
- [Unity ECS] 游戏对象转换和子场景 [1]
游戏只是关于玩家输入改变数据,然后看到不同呈现的事物,因此玩得开心.这些数据是使用 Unity 的 WYSIWYG 工具在scene设计的.但是那些基于 GameObject 的数据与 ECS 不 ...
- 自定义java对象转换工具类
背景 项目中经常有VO.PO.DTO等之间转换,由于apache工具类中BeanUtils.copyProperties及Json序列化反序列化方式转换性能比较低(阿里巴巴规范检查有提示不建议采用). ...
- Java中的dozer对象转换
Java中的dozer对象转换 1.dozer介绍 Dozer是Java Bean到Java Bean映射器,它以递归方式将数据从一个对象复制到另一个对象. dozer是用来对两个对象之间属性转换的工 ...
- 我写了个IDEA开源插件,vo2dto 一键生成对象转换
头炸,po2vo.vo2do.do2dto,一堆对象属性,取出来塞进来.要不是为了 DDD 架构下的各个分层防腐,真想一竿子怼下去. 那上 BeanUtils.copyProperties 呀,其实对 ...
- Java对象转换最佳方案
系统变的复杂,系统的层次划分越来越细,边界也越来越明确. 然后每一层之间一般都有自己要处理的领域对象,统称为pojo一般在model或者domain包下(类的后缀不能为pojo). 常见的一些模型类型 ...
最新文章
- leetcode-回文数(简单)
- 转:入侵网站必备-sql server
- 二进制在计算机电路中得到广泛的应用,电子技术与单片机的发展应用2喜欢就下吧(全文完整版)...
- JS:1.3,函数(function)
- 如何锻炼膝盖和膝盖周围肌肉_我的分享膝盖照片的社交网络将如何拯救世界
- ProgressDialog弹出时的底色变暗(转)
- python输入y继续运行_Python二三事 - 接触Python(x,y)
- 牛逼!9种不同的方法帮助你提高国内访问Github的速度到2MB/s以上...
- pytorch模型初始化
- Silverlight-style
- 计算机软件销售收入会计,嵌入式软件产品销售额如何计算
- Web前端JSP面试题
- Origin软件绘制柱形图
- property_get和property_set使用方法
- 多视图信息瓶颈表征学习
- Java 根据输入的a、b、c,计算三角形面积和周长。根据程序上下文以及输入输出样例,填写程序空白,使程序完整
- windows10安装Python 3.xx.xx,勾选 Download debugging symbols或Download debug binari两项安装失败解决办法
- mysql的pv跟pc_PC板PV板PVC板PPV板区别与用途
- 前台使用viewbag
- 敢用这张图片做“壁纸”手机秒变砖!
热门文章
- Python代码选中文乱码
- python的深拷贝与浅拷贝
- Spring 学习笔记
- ACM学习历程—HDU5586 Sum(动态规划)(BestCoder Round #64 (div.2) 1002)
- Java基础知识强化之IO流笔记41:字符流缓冲流之复制文本文件案例02(使用 [ newLine() / readLine() ] )(重要)...
- Oracle面试问题汇总
- [PyQt4]项目开发中遇到的错误与解决办法
- 各大IT公司笔试真题汇总开发人员一定要加入收藏夹的网站(收藏)
- Cookie注入是怎样产生的
- 刻意练习:LeetCode实战 -- Task05. 最接近的三数之和