MapStruct对象映射转换解决Bean属性拷贝性能问题

作者:心城以北 时间:2023-05-14 04:10:55 

简介

MapStruct 是一个代码生成器(可以生成对象映射转换的代码),它基于约定优于配置的方法,极大地简化了 Java bean 类型之间的映射实现。

生成的映射代码使用普通的方法调用,因此速度快、类型安全且易于理解。

适用场景

多层应用程序通常需要在不同的对象模型(例如实体和 DTO)之间进行映射。编写这样的映射代码是一项乏味且容易出错的任务。MapStruct 旨在通过尽可能地自动化来简化这项工作。

与其他映射框架相比,MapStruct 在编译时生成 bean 映射,这确保了高性能,允许快速的开发人员反馈和彻底的错误检查。

说白了就解决 beanCopy 的问题。

工作时机

MapStruct 是一个注解处理器,它插入到 Java 编译器中,可用于命令行构建(Maven、Gradle 等)以及您首选的 IDE。

MapStruct 使用合理的默认值,但在配置或实现特殊行为时会采取措施。

使用案例

1、添加依赖

// mapstruct
implementation 'org.mapstruct:mapstruct:1.4.2.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'
复制代码

2、定义两个类

一个 Car 类(JPA 实体类)

一个 CarDto 类(数据传输类)

这两个类型非常相似,只是在计数属性的字段名不同,并且 type 属性是 CarType 枚举类型,CarDto 中是字符串类型。

Car 类

public class Car {
   private String make;
   private int numberOfSeats;
   private CarType type;
   //constructor, getters, setters etc.
}

CarType 类定义

public enum CarType {
   SEDAN;
}

CarDto 类

public class CarDto {
   private String make;
   private int seatCount;
   private String type;
   //constructor, getters, setters etc.
}

创建转换器类接口,定义需要将 Car 对象转换为 CarDto 对象

@Mapper
public interface CarMapper {
   CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
   @Mapping(source = "numberOfSeats", target = "seatCount")
   CarDto carToCarDto(Car car);
}

1). @Mapper 注解将该接口标记为映射接口,并且让 MapStruct 处理器在编译期间进行处理,实际映射方法为 carToCarDto 目的就是原参数Car,转换为方法返回结果对象 CarDto

2). 对于源对象和目标对象中有不同的属性名称,我们可以使用 @Mapping 注解进行映射。在默认情况下,将源对象和目标对象据欧不同的类型属性执行类型转换,例如,type 数据原来是枚举,可以自动转换为字符串。

3). 以一个 Mapper 接口也支持多个映射方法。所有的这些方法都由 MapStruct 框架来实现。我们可以从 Mappers类中检索接口实现的实例。通常我们在接口中申明一个 INSTANCE 属性,提供对外访问的实例。

3、单元测试

@Test
public void shouldMapCarToDto () {
   //given
   Car car = new Car("Morris", 5, CarType.SEDAN);
   //when
   CarDto carDto = CarMapper.INSTANCE.carToCarDto(car);
   //then
   assertThat(carDto).isNotNull();
   assertThat(carDto.getMake()).isEqualTo("Morris");
   assertThat(carDto.getSeatCount()).isEqualTo(5);
   assertThat(carDto.getType()).isEqualTo("SEDAN");
}

我们使用起来就是非常简单,运行结果如下:

MapStruct对象映射转换解决Bean属性拷贝性能问题

核心总结

MapStruct其实和 Lombok 有些类似,也是通过插件的方式在我们编译期为我们生成一些辅助的代码。但是MapStruct 专注是解决 BeanCopy 以及对象转换的场景。

下面我们看看,就是我们 CarMapper 的实现类 CarMapperImpl , 这些都是框架在编译期间,我们生成的代码。

MapStruct对象映射转换解决Bean属性拷贝性能问题

如果我们使用 BeanUtils.copyProperties来做对象的转换是需要通过反射来获取对象的属性,方法等信息。然后再去赋值。反射虽然能够解决一些通用性的场景,但是对于频繁的 List 复制,性能是不高的。我们可以看看下面copyProperties的部分代码截图:

MapStruct对象映射转换解决Bean属性拷贝性能问题

个人觉得 MapStruct的优势还是非常明显的,就是帮助我们少写了非常多的 getters, setters 进行对象的相互转换,性能高于任何一种属性复制。缺点就会降低程序编译速度,增加转换层提升代码复杂度。

参考文档

  • mapstruct.org

  • github.com/mapstruct/m…

来源:https://juejin.cn/post/7063112114784698399

标签:MapStruct,Bean,对象映射,属性拷贝
0
投稿

猜你喜欢

  • 为什么Java项目中别用!=null做判空

    2023-12-19 20:26:13
  • Android 自定义view实现进度条加载效果实例代码

    2022-12-21 05:33:48
  • C#中的静态成员、静态方法、静态类介绍

    2022-04-25 20:06:51
  • Android App支付系列(二):支付宝SDK接入详细指南(附官方支付demo)

    2022-03-14 01:12:28
  • Android自定义View实现带4圆角或者2圆角的效果

    2023-04-08 04:32:10
  • Spring MVC 学习 之 - URL参数传递详解

    2022-03-04 22:05:12
  • c#判断代码是否执行超时的几种方式总结

    2023-03-11 16:33:02
  • MyEclipse设置Console输出到文件的实现方法

    2022-01-14 10:37:03
  • C#实现一个控制台的点餐系统

    2023-09-03 20:47:24
  • Java MultipartFile实现上传文件/上传图片

    2022-04-19 07:07:19
  • Android实现底部状态栏切换的两种方式

    2022-03-11 02:46:47
  • Android TabHost如何实现顶部选项卡

    2023-04-13 01:08:14
  • mybatis 报错显示sql中有两个limit的解决

    2022-04-30 02:50:49
  • Android实现未读消息小红点显示实例

    2022-05-18 07:57:27
  • java 较大数据量取差集,list.removeAll性能优化详解

    2022-11-06 16:52:15
  • C#版的 Escape() 和 Unescape() 函数分享

    2023-07-05 01:55:20
  • java遍历Map的几种方法分析

    2023-12-04 22:34:27
  • 基于Viewpager2实现登录注册引导页面

    2023-06-16 11:04:10
  • Android Studio 报错failed to create jvm error code -4的解决方法

    2023-01-22 03:13:49
  • Android通过XListView实现上拉加载下拉刷新功能

    2023-02-26 23:30:03
  • asp之家 软件编程 m.aspxhome.com