MapStruct与BeanUtils处理对象属性复制场景对比

MapStruct是什么?

MapStruct is a code generator that greatly simplifies the implementation of mappings between Java bean types based on a convention over configuration approach.

The generated mapping code uses plain method invocations and thus is fast, type-safe and easy to understand.

MapStruct是一个基于Java注解的代码生成器,它用于在编译时生成Java Bean之间的映射代码。它的实现原理基于JSR 269,这是JDK引进的一种规范,允许在编译期处理注解,并且读取、修改和添加抽象语法树中的内容。

在定义了一个包含MapStruct注解的映射器接口后,MapStruct的注解处理器会在编译时扫描这些接口,并生成对应的实现类。这些实现类包含了将源对象映射到目标对象的具体代码,它们使用纯Java的方法调用,而非反射机制,因此具有高性能和类型安全的特性

MapStruct的主要特点:

  1. 类型安全:通过编译时生成代码,确保了源对象和目标对象之间的映射是类型安全的。这有助于在编写代码时更容易地检测到错误,并减少运行时错误的风险。
  2. 高性能:由于MapStruct生成的代码是在编译时生成的,并且直接调用这些实现类的方法,因此在运行时执行对象映射时速度非常快,不需要进行反射调用。
  3. 支持多种映射策略:MapStruct支持多种映射策略,包括注释、名称约定和自定义映射方法等,以满足不同的转换需求。
  4. 易于集成:MapStruct可以无缝集成到Spring等IoC容器中,方便地将MapStruct转换器注入到应用程序中。

MapStruct适用场景:

MapStruct适用于各种Java Bean之间的转换场景,包括但不限于以下情况:

  1. DTO(Data Transfer Object)和Entity之间的转换。
  2. 不同版本API之间的数据映射。
  3. 前端页面展示数据和后端数据模型之间的转换。

在这些场景中,MapStruct可以帮助开发者简化转换代码的编写,提高开发效率,减少出错的可能性。

代码示例:(jdk8+maven+Intellj Idea 2021.3.1)

pom.xml加入依赖

<!-- MapStruct core dependency --><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>${mapstruct.version}</version></dependency><!-- MapStruct annotation processor (needed for compile-time code generation) --><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>${mapstruct.version}</version><scope>provided</scope></dependency>

 编写源对象和目标对象:

public class Car {  private String make;  private String model;  // getters and setters  
}  public class CarDto {  private String make;  private String model;  // getters and setters  
}

定义映射接口:

@Mapper  
public interface CarMapper {  CarDto carToCarDto(Car car);  Car carToCar(CarDto carDto);  // 其他映射方法...  
}

自定义映射:

在某些情况下,你可能需要进行一些自定义映射操作。MapStruct提供了多种方式来支持自定义映射。

  • 使用@Mapping注解:你可以使用@Mapping注解来指定源属性和目标属性之间的映射关系。

@Mapper  
public interface CarMapper {  @Mapping(source = "carId", target = "id")  CarDto carToCarDto(Car car);  // ...  
}
  • 自定义类型转换:你可以通过编写自定义的转换方法或使用MapStruct提供的类型转换注解(如@NumberFormat@DateTimeFormat等)来实现复杂的类型转换。
  • 使用@Qualifier:在存在多个转换方法的情况下,你可以使用@Qualifier注解来指定使用哪个方法。
  • 后处理器:在某些情况下,你可能需要在映射完成后进行一些操作。这时,你可以使用MapStruct的后处理器功能。

 使用映射器:

一旦你定义了映射接口并配置了必要的映射方法,MapStruct将在编译时自动生成这个接口的实现类。你可以通过Mappers.getMapper()方法或其他依赖注入机制来获取映射器实例,并使用它来执行映射操作。

CarMapper carMapper = Mappers.getMapper(CarMapper.class);  
CarDto carDto = carMapper.carToCarDto(car);

 在这个例子中,我们通过Mappers.getMapper()方法获取了CarMapper的实例,并使用它将一个Car对象转换为一个CarDto对象。

注意事项:

  • 确保你的IDE或构建工具支持注解处理器。这通常需要在IDE的设置中启用注解处理器,或者在构建工具的配置文件中添加相应的插件或配置。
  • 如果你在使用Lombok,并且遇到了与MapStruct的兼容性问题,请确保Lombok的版本与MapStruct的版本兼容。
  • 在编写映射方法时,尽量使用简单的getter/setter方法调用,避免在映射方法中进行复杂的业务逻辑操作。这样可以提高映射的性能和可维护性。

BeanUtils:(以commons-beanutils为例)

BeanUtils是Apache Commons项目的一部分,它提供了一组用于复制Java Bean属性的实用程序方法。

MapStruct与BeanUtils处理对象属性复制场景对比:

MapStruct与BeanUtils在处理对象属性复制的场景中存在明显的差异,下面将从多个方面对它们进行对比:

  • 技术原理
    • MapStruct:基于JSR 269的Java注释处理器,用于生成类型安全的Bean映射类。在编译过程中,MapStruct会生成映射器接口的实现,这些实现使用纯Java方法调用在源对象和目标对象之间进行映射,无需反射或类似操作。
    • BeanUtils:在Spring框架中,BeanUtils.copyProperties方法用于将一个Java对象的属性值复制到另一个对象中。其实现机制通常基于反射。
  • 性能
    • MapStruct:由于使用纯Java方法调用,MapStruct通常比基于反射的工具(如BeanUtils)具有更好的性能。特别是当处理大量对象拷贝时,MapStruct的性能优势更加明显。
    • BeanUtils:基于反射的实现可能会导致性能下降,尤其是在处理大量对象时。
  • 类型安全性
    • MapStruct:编译时类型安全,只能映射彼此映射的对象和属性,避免了意外的类型错误。
    • BeanUtils:运行时类型安全,如果在运行时源对象和目标对象的属性类型不匹配,可能会抛出异常。
  • 配置和灵活性
    • MapStruct:支持复杂的映射关系,如嵌套对象、集合、自定义映射方法等。通过注解可以灵活配置映射规则。
    • BeanUtils:支持基本的属性复制,但对于复杂的映射关系可能需要额外的代码来处理。
  • 错误报告
    • MapStruct:在构建时清除错误报告,如果映射不完整或映射不正确,可以在编译时发现问题。
    • BeanUtils:在运行时发现问题,可能会抛出异常。
  • 集成与依赖
    • MapStruct:需要额外的依赖项,但通常不会对现有项目产生太大影响。可以与多种Java项目集成。
    • BeanUtils:如果项目已经集成了Spring框架,那么BeanUtils是现成的选择,无需额外依赖。
  • 使用场景
    • MapStruct:适用于对性能有较高要求、需要处理大量对象拷贝、支持复杂映射关系的场景。
    • BeanUtils:适用于简单的属性复制场景,尤其是在已经集成了Spring框架的项目中。

综上所述,MapStruct和BeanUtils各有优缺点,适用于不同的场景。在选择使用哪个工具时,需要根据具体业务场景和需求进行权衡取舍。如果需要处理大量对象拷贝、支持复杂映射关系且对性能有较高要求,建议使用MapStruct;如果项目已经集成了Spring框架且只需要简单的属性复制,那么BeanUtils是一个不错的选择。

mapstruct官网传送门:

MapStruct – Java bean mappings, the easy way!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/843630.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

elastich运维

Elastichsearch是一种高度可扩展的开源全文搜索和分析引擎&#xff0c;可以用来实现快速、高效的数据检索。 集群规划与部署&#xff1a;首先需要根据业务需求规划Elastichsearch集群的节点数量和角色&#xff08;如主节点、副本节点、协调节点等&#xff09;。在部署时&#x…

赎金信-力扣

这道题想到的解法是使用一个哈希表来存储magazine里每个字符出现的次数&#xff0c;然后遍历ransomNote&#xff0c;出现对应的字母则哈希表中对应的值减一&#xff0c;当查找不到某个字符&#xff0c;或者某个字符的值小于0时&#xff0c;则返回false。代码如下&#xff1a; …

ORACLE中递归遍历

--查询全部资源信息 select * from urm_class_info --向上遍历树&#xff0c;找到路径直到根节点&#xff0c;指定的是parentid select distinct classid, parentid, namefrom urm_class_infostart with parentid cmdb0000000000000017 connect by prior parentid classid …

配置Spring Security的身份验证

配置Spring Security的身份验证 在我们登录Spring Security之前&#xff0c;我们将向您展示如何配置Spring Security的身份验证。我们将通过创建一些用户来验证并为它们生成身份验证。在这篇文章中&#xff0c;我们将学习Spring Security的流程是配置Spring Security中的身份验…

代码随想录算法训练营第二十一天 | 530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

530.二叉搜索树的最小绝对差 题目链接&#xff1a;https://leetcode.cn/problems/minimum-absolute-difference-in-bst/ 文档讲解&#xff1a;https://programmercarl.com/0530.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E7%9A%84%E6%9C%80%E5%B0%8F%E7%BB%9D%E5%AF%B9%E…

VMware Workstation 不可恢复错误:(vmui) 错误代码0xc0000094

软件版本 vmware 17 错误情况 VMware Workstation 不可恢复错误&#xff1a;(vmui) Exception 0xc0000094 has occurred. 问题原因 VMware升级到17.0后&#xff0c;将虚拟机环境的【硬件兼容性】升级至Workstation 17.X后&#xff0c;无法修改设备参数。 解决办法 打开需…

企业营收分析难?搞定收入认领月底不加班!

在当今日益激烈的市场竞争中&#xff0c;企业的营收分析不仅是衡量经营成果的关键指标&#xff0c;更是指导企业未来发展的重要依据。然而&#xff0c;对于许多企业来说&#xff0c;营收分析的过程往往繁琐且耗时&#xff0c;尤其是月底结账时&#xff0c;大量的数据和复杂的计…

【Numpy】NumPy基础入门:创建和管理多维数组

NumPy基础入门&#xff1a;创建和管理多维数组 简介 NumPy&#xff08;Numerical Python的简称&#xff09;是Python语言的一个基础科学计算库&#xff0c;广泛应用于数据分析、机器学习、科学计算和工程领域。NumPy的核心是其强大的N维数组对象ndarray&#xff0c;它为Pytho…

医疗图像处理2023:Transformers in medical imaging: A survey

医学成像中的transformer:综述 目录 一、介绍 贡献与安排 二、CNN和Transformer 1.CNN 2.ViT 三、Transformer应用于各个领域 1.图像分割 1&#xff09;器官特异性 ①2D ②3D 2&#xff09;多器官类别 ①纯transformer ②混合架构 单尺度 多尺度 3&#xff09;…

fyne表单布局

fyne表单布局 layout.FormLayout就像一个 2 列网格布局 。 package mainimport ("image/color""fyne.io/fyne/v2/app""fyne.io/fyne/v2/canvas""fyne.io/fyne/v2/container""fyne.io/fyne/v2/layout" )func main() {myApp…

electron 如何升级版本

electron-updater使用指南 基础 检测是否最新版 autoUpdater.checkForUpdates() 下载最新版 autoUpdater.downloadUpdate() 项目使用 update.js const { ipcMain } require(electron) const { autoUpdater } require(electron-updater) const path require("pa…

Wpf 使用 Prism 实战开发Day27

首页汇总和数据动态显示 一.创建首页数据汇总数据接口 汇总&#xff1a;待办事项的总数已完成&#xff1a;待办事项里面有多少条完成的待办完成比例&#xff1a;已完成和汇总之间的比例备忘录&#xff1a;显示备忘录的总数待办事项&#xff1a;显示待办事项未完成的集合备忘录&…

②单细胞学习-组间及样本细胞比例分析

目录 数据读入 每个样本各细胞比例 两个组间细胞比例 亚组间细胞比例差异分析&#xff08;循环&#xff09; 单个细胞类型亚新间比例差异 ①单细胞学习-数据读取、降维和分群-CSDN博客 比较各个样本间的各类细胞比例或者亚组之间的细胞比例差异 ①数据读入 #各样本细胞…

三、Ollama导入大模型(.Net8+SemanticKernel+Ollama)本地运行自己的大模型

Ollama导入大模型 一、导入Ollama大模型1、使用run命令2、使用Modelfile方式 二、导入自定义大模型&#xff08;Ollama官网以外的大模型&#xff09;三、使用OpenWebUI导入大模型 Ollama可以导入官方提供的大模型&#xff0c;也可以导入huggingface上的自定义大模型&#xff08…

【加密与解密(第四版)】第十四章笔记

第十四章 漏洞分析技术 14.1 软件漏洞原理 缓冲区溢出漏洞&#xff1a;栈溢出 堆溢出、整型溢出&#xff08;存储溢出、计算溢出、符号问题&#xff09; UAF&#xff08;Use-After-Free&#xff09;漏洞 14.2 ShellCode 功能模块&#xff1a;下载执行、捆绑、反弹shell 14.3 …

【NumPy】使用NumPy计算相关系数:详解numpy.corrcoef函数及应用

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

MySQL之性能剖析(二)

MySQL之性能剖析 通过性能剖析进行优化 一旦掌握并时间面向响应时间的优化方法&#xff0c;就会发现需要不断地对系统进行性能剖析(profiling). 性能剖析是测量和分析时间花费在哪里的主要方法。性能剖析一般有两个步骤:测量任务所花费的时间&#xff1b;然后对结果进行统计和…

基础8 探索JAVA图形编程桌面:邮件操作组件详解

在一个静谧的午后&#xff0c;卧龙和凤雏相邀来到一家古朴典雅的茶馆。茶馆内环境清幽&#xff0c;袅袅的茶香与悠扬的古筝声交织在一起&#xff0c;营造出一种宁静而祥和的氛围。 卧龙和凤雏坐在茶馆的一角&#xff0c;面前的桌子上摆放着一套精致的茶具。茶香四溢&#xff0c…

C++ STL 中的自定义比较:深入理解相等和等价

STL 中的自定义比较、相等和等价 一、简介二、STL 的排序部分三、STL 的未排序部分四、比较元素五、实现比较器六、总结 一、简介 本文主要讨论了在 STL 中使用自定义比较函数&#xff0c;以及比较操作中的相等和等价概念。 有如下的代码&#xff1a; std::vector< std::…

HTML并集,交集,子代,后代选择器

1,交集选择器 他们必须满足既是p又是.box的关系&#xff08;直接连写&#xff0c;没有任何符号&#xff09; p.box{color:red; } <div class"box"> 1 </div> <p class"box">2</p> <p>3</p> 2.并集选择器 将div,p,…