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

 更新时间:2022年02月11日 15:44:21   作者:心城以北  
无意间看到项目中有小伙伴用到了 MapStruct 来做对象映射转换当时我就很好奇,这个是什么框架,能够解决什么问题,带着这两个疑问就有了下面的文章

简介

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

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

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

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

参考文档

以上就是MapStruct对象映射转换解决Bean属性拷贝性能问题的详细内容,更多关于MapStruct解决Bean属性拷贝的资料请关注脚本之家其它相关文章!

相关文章

  • 详解用maven将dubbo工程打成jar包运行

    详解用maven将dubbo工程打成jar包运行

    这篇文章主要介绍了详解用maven将dubbo工程打成jar包运行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • 详解SpringBoot Mongo 自增长ID有序规则

    详解SpringBoot Mongo 自增长ID有序规则

    本文主要介绍springboot基于mongodb有序id生成,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • Mybatis如何开启控制台打印sql语句

    Mybatis如何开启控制台打印sql语句

    在SpringBoot与Mybatis整合开发中,开启控制台SQL语句打印是一个常见需求,有助于调试与性能优化,方法一:在Mybatis配置文件mybatis-config.xml中添加设置;方法二:在SpringBoot配置文件application.yml或properties中
    2024-11-11
  • 用html css javascript打造自己的RIA图文教程

    用html css javascript打造自己的RIA图文教程

    用html&css&javascript打造自己的RIA之一,包括了配置等
    2009-07-07
  • Java中的Scanner、BufferedReader 和 StreamTokenizer使用详解

    Java中的Scanner、BufferedReader 和 StreamTokenizer使用详解

    Scanner是Java 中一个用于解析原始类型(如 int、double 等)和字符串的类,它通常从输入流中逐个读取数据并进行解析,支持多种分隔符的使用,本文介绍Java中的Scanner、BufferedReader 和 StreamTokenizer的相关知识,感兴趣的朋友一起看看吧
    2025-02-02
  • Java判断字节流是否是 UTF8编码方法示例

    Java判断字节流是否是 UTF8编码方法示例

    这篇文章主要我大家介绍了Java判断字节流是否是 UTF8编码方法示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • nacos一直频繁的打印日志get changegroupkeys问题

    nacos一直频繁的打印日志get changegroupkeys问题

    这篇文章主要介绍了nacos一直频繁的打印日志get changegroupkeys问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • Java中ScheduledExecutorService介绍和使用案例(推荐)

    Java中ScheduledExecutorService介绍和使用案例(推荐)

    ScheduledExecutorService是Java并发包中的接口,用于安排任务在给定延迟后运行或定期执行,它继承自ExecutorService,具有线程池特性,可复用线程,提高效率,本文主要介绍java中的ScheduledExecutorService介绍和使用案例,感兴趣的朋友一起看看吧
    2024-10-10
  • Spring Utils工具类常用方法实例

    Spring Utils工具类常用方法实例

    这篇文章主要介绍了Spring Utils工具类常用方法实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • SpringBoot实现过滤器Filter的三种方式

    SpringBoot实现过滤器Filter的三种方式

    过滤器Filter由Servlet提供,基于函数回调实现链式对网络请求与响应的拦截与修改,本文讲给大家详细介绍SpringBoot实现过滤器Filter的三种方式,需要的朋友可以参考下
    2023-08-08

最新评论