信息发布→ 登录 注册 退出

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

发布时间:2026-01-11

点击量:
目录
  • 简介
  • 适用场景
  • 工作时机
  • 使用案例
    • 1、添加依赖
    • 2、定义两个类
    • 3、单元测试
  • 核心总结

    简介

    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.org
    • github.com/mapstruct/m…

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

    在线客服
    服务热线

    服务热线

    4008888355

    微信咨询
    二维码
    返回顶部
    ×二维码

    截屏,微信识别二维码

    打开微信

    微信号已复制,请打开微信添加咨询详情!