MapStruct原理解析

这篇具有很好参考价值的文章主要介绍了MapStruct原理解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

关键词

JSR-269、编译原理、生成树AST、SPI机制、FreeMarker

要想搞懂mapstruct的底层实现原理,需要先知道java编译流程:.java源文件经过编译器编译成为.class文件,虚拟机执行的就是.class文件

一.语法树

抽象语法树(Abstract Syntax Tree,AST)是在编译器的编译过程中生成的一种数据结构,用于表示源代码的语法结构。

在 Java 的编译过程中,生成 AST 的步骤通常包括以下几个阶段:

词法分析(Lexical Analysis):也称为扫描(Scanning),将源代码分解成一个个的词法单元(Token)。词法单元可以是关键字、标识符、运算符、常量等。

语法分析(Syntax Analysis):也称为解析(Parsing),根据词法单元构建语法树。语法分析器使用文法规则(例如上下文无关文法)来检查词法单元是否符合语法规则,并生成抽象语法树。

语义分析(Semantic Analysis):在生成 AST 的同时,进行语义检查。语义分析器会对语法树进行类型检查、作用域分析、常量表达式计算等。它还会将符号链接到声明,以便后续引用。

中间代码生成(Intermediate Code Generation):有些编译器会在 AST 基础上生成一种中间表示形式,例如三地址码或虚拟机指令。这些中间代码通常更容易进行优化和目标代码生成。

目标代码生成(Code Generation):将 AST 或中间代码转换成目标平台的机器代码。这个阶段将 AST 的每个节点映射到目标机器的指令,生成可以直接执行的最终可执行文件。

因此,AST 的生成通常发生在词法分析和语义分析之间。它是编译过程中重要的中间表示形式,用于表示源代码的语法结构,并为后续的优化和代码生成提供基础。

二.lombok原理

lombok与MapStruct原理都是基于JSR-269规范:

初次使用lombok时,都需要在idea安装lombok插件,这让我们怀疑lombok的实现是通过提供自己的编译器实现的,然而实际情况并非如此,在脱离idea使用javac编译时,只要类路径有lombok的jar包,项

目也可以正常编译通过。其原理在于JSR-269规范。

1.JSR-269规范

JSR 269 规范定义了 Java 编译时注解处理器 API(Pluggable Annotation Processing API(插件式注解处理器)),提供了一种标准的方式让开发者在编译时自动
化处理 Java 源代码中的注解
。具体步骤如下:

  1. 自定义注解

  2. 继承AbstractProcessor类,重写process方法实现自己的注解处理逻辑

说明:AbstractProcessor在JDK的rt.jar里面的javax.annotation.processing包下面;同时生成impl类用的也是这个包下面的Filer接口的createSourceFile方法,SupportedAnnotationTypes注解、SupportedOptions注解、SupportedSourceVersion注解也都在,这三个注解目前只看到Mapstruct底层有用到
MapStruct原理解析

  1. 在META-INF/services目录下创建javax.annotation.processing.Processor文件注册自己实现的Annotation Processor(全路径名)

  2. 编译项目并deploy jar包到maven仓库,在其他项目引入该jar包,在接口上加上我们自定义的注解

在javac编译时即可调用到我们的注解处理器Annotation Processor,从而使得我们有机会对java编译过程中生产的抽象语法树进行修改。

2.原理

javac的编译过程,大致可以分为3个过程:

(1)解析与填充符号表过程

(2)插入式注解处理器的注解处理过程

(3)分析与字节码生成过程

解析与填充符号表过程会将源码转换为一棵抽象语法树(Abstract Syntax Tree,AST),AST是一种用来描述程序代码语法结构的树形表示方式,语法树的每一个节点(每个节点都是JCTree类的子类)都代表着程序代码中的一个语法结构
(Construct),例如包、类型、修饰符、运算符、接口、返回值甚至代码注释等都可以是一个语法结构。在插入式注解处理器的注解处理过程中,lombok对第一步骤得到的AST进行处理,找到类似@Data注解所在类对应的语法树(AST),然后修改该语法树(AST),(TreeMaker提供方法可以修改)增加getter和setter等方法的相应树节点,javac使用修改后的抽象语法树(AST)生成字节码文件,因此最终生成的class文件中包含了这些
自动生成的getter,setter方法。

二.mapstruct原理

MapStruct 是用于 Bean 之间映射的工具库之一,其底层实现就是基于JSR-269。
阅读源码

(1)发现 mapstruct主要有两个jar包

MapStruct原理解析


(2)通过根据JSR-269可以知道MappingProcessor就是mapstruct的入口

MapStruct原理解析


(3)com.sun.tools.javac.main.JavaCompiler#compile方法的有段代码在编译的时候会调用到MappingProcessor

说明

com.sun.tools.javac.main.JavaCompiler 是 Java 编译器的主要类,它是 JDK 中 javac 命令行工具的实现。该类负责解析和编译 Java 源代码,并生成字节码文件。
JavaCompiler 类位于 com.sun.tools.javac.main 包中,属于 JDK 内部实现的一部分,并不是公开的 API。它提供了编译 Java 代码的核心功能

MapStruct原理解析


(4)Mapper注解定义如下

MapStruct原理解析


(5)MappingProcessor实现如下

MapStruct原理解析


process方法实现注解处理逻辑做代码改造工作。

MapStruct原理解析


(6)impl实现类生成

proess方法-->
processMapperElements( deferredMappers, roundContext );
-->processMapperTypeElement( context, mapperElement );
--->model = process( context, processor, mapperTypeElement, model );
--->processor.process( context, mapperTypeElement, sourceElement );
--->MapperRenderingProcessor类里可以看到有个createSourceFile方法(Filer 接口),该方法会创建xxxxImpl类。
MapStruct原理解析


另外,MapStruct 库的注解处理器生成源代码文件利用了模板引擎 FreeMarker 库。如图可以看到FreeMarker利用模板生成setter方法

MapStruct原理解析


如下后缀为ftl的文件即为FreeMarker模板文件
MapStruct原理解析

三.Debug模式跟踪代码

  1. 打开你的项目并转到 "Run/Debug Configurations" 对话框。
  2. 在左上角的工具栏中,点击下拉箭头旁边的 "Edit Configurations" 按钮。
  3. 在弹出的对话框中,选择 "Maven" 选项,并点击加号按钮以创建一个新的Maven配置。
  4. Command line输入"Compile"
  5. 选择项目工程然后apply

参考链接:
https://juejin.cn/post/6956190395319451679
https://blog.csdn.net/weixin_43983762/article/details/105867398
https://blog.csdn.net/begefefsef/article/details/126434950
https://developer.aliyun.com/article/944036
https://nullwy.me/2017/04/javac-api/

以下是来自chatgpt的回答:

1.MapStruct原理
是一个Java注解处理器,它基于编译时代码生成的原理,用于自动化Java bean类型之间的映射工作。以下是MapStruct的工作原理的详细解读:

注解处理: 在Java编译阶段,MapStruct通过Java的注解处理器API(JSR 269)扫描源代码中的接口或抽象类,这些接口或抽象类使用了MapStruct提供的注解,如@Mapper或@Mapping。

抽象方法解析: MapStruct分析这些接口或抽象类中定义的抽象方法,这些方法通常表示从一个bean类型转换到另一个bean类型的映射。MapStruct解析方法参数和返回值,确定源类型和目标类型。

属性映射分析: MapStruct使用内置的策略或者通过@Mapping注解指定的策略来分析两个bean之间属性的对应关系。如果属性名称相同且类型兼容,MapStruct会自动映射这些属性。

代码生成: 一旦分析完毕,MapStruct会为每个映射接口生成一个实现类。这个实现类包含了具体的映射逻辑,能够将一个对象的属性复制到另一个对象的相应属性中。

编译时优化: 因为所有的映射代码都是在编译时生成的,所以运行时没有反射的开销,这意味着MapStruct生成的代码在性能上与手写的映射代码类似。

类型转换: 如果源属性和目标属性的类型不匹配,MapStruct会尝试使用内置的类型转换器或者开发者可以自定义转换逻辑来进行转换。

嵌套属性和集合: MapStruct也支持嵌套属性的映射和集合类型的映射,允许复杂的数据结构之间的转换。

更新现有对象: 除了创建目标类型的新实例之外,MapStruct还允许将属性映射到现有的实例上。

构建工具集成: MapStruct可以很容易地与Maven或Gradle等构建工具集成,自动在编译过程中执行代码生成。

IDE集成: 由于MapStruct是在编译时生成代码,所以大多数Java IDE都能够很好地支持MapStruct,包括在生成的实现类中进行代码跳转和调试。

综上所述,MapStruct的主要优点是它通过在编译时生成映射代码,从而提供快速、类型安全并且易于维护的映射代码,而不需要开发者手动编写大量的映射逻辑。

2.Java的注解处理器API(JSR 269)说明如下
Java的注解处理器API(JSR 269),正式名称为Pluggable Annotation Processing API,是Java SE 6中引入的一项功能,允许开发者创建自定义注解处理器,这些处理器在编译时可以检查和处理注解。这是MapStruct工作原理的核心部分。以下是注解处理器如何在MapStruct中工作的详细说明:

编译器集成: 注解处理器在Java编译器(javac)的编译过程中运行。当javac编译Java源代码时,它会检查源代码中使用的注解。

发现注解处理器: 开发者可以通过在服务配置文件中声明或者使用编译器参数来指定注解处理器。MapStruct的注解处理器被声明在META-INF/services/javax.annotation.processing.Processor文件中,所以javac能够自动加载并调用它。

处理注解: 一旦javac发现了MapStruct的注解处理器,它会将所有使用了MapStruct注解(如@Mapper)的源代码元素(类、接口、方法等)传递给处理器。MapStruct的处理器会分析这些元素。

抽象语法树(AST): 注解处理器可以访问抽象语法树(AST),这是源代码的一个结构化表示。通过AST,处理器可以读取类、方法、字段和它们的注解等信息。

生成代码: 注解处理器可以生成新的源代码文件。MapStruct的处理器使用这个能力来生成实现了映射接口的具体类。这些生成的类包含了必要的映射逻辑,将一个对象的属性转换到另一个对象。

类型检查: 注解处理器还可以进行类型检查,确认注解的使用是否符合预期的规则。如果不符合,它可以生成编译错误或警告。

环回机制: 如果注解处理器生成新的代码,这些代码可能包含新的注解,javac会在后续的编译轮次中处理这些新生成的代码。这个过程会一直进行,直到没有新的注解处理器输出为止。

多轮处理: 注解处理器可能会在多轮编译过程中运行。在每一轮中,处理器会接收到当前轮次未处理的注解类型。处理器必须管理它在每一轮中的状态,因为它可能需要在多轮中累积信息。

总结来说,MapStruct通过注解处理器在编译时分析使用了MapStruct注解的源代码,并生成相应的映射类。这一切都在Java编译器的控制之下进行,确保了生成的代码是即时和准确的,而且不会对运行时性能产生影响。

3.META-INF文件夹用来做什么的
META-INF目录是Java JAR文件的一部分,它用于存储JAR文件的元数据,也就是关于JAR包本身的数据和配置信息。这个目录通常包含以下几种类型的文件和子目录:

MANIFEST.MF: 这是JAR文件中最重要的文件之一,位于META-INF目录下。它包含了JAR文件的元数据,例如主类(Main-Class)的名称、JAR文件的版本、创建者信息、包的签名信息等。Java运行时使用这些信息来执行和验证JAR文件。

签名文件和签名块文件: 如果JAR文件被签名,那么签名文件(.SF或.DSA或.RSA文件)和签名块文件(.RSA或.DSA或.EC文件)会被放在META-INF目录下。这些文件用来验证JAR文件的完整性和来源。

服务提供者配置文件: 用于服务加载机制的配置文件(如javax.annotation.processing.Processor),它们通常放在META-INF/services目录下,这些文件用来指定服务接口的实现类,以供服务加载器使用。

其他资源文件: 除了上述文件外,META-INF目录还可以包含其他资源文件,如属性文件、配置文件、图片等,这些文件通常由JAR包内的应用程序使用。

索引文件: 有时候,META-INF目录还可能包含用于加速类加载的索引文件(如INDEX.LIST)。

在Java EE或者其他Java技术栈中(如OSGi),META-INF目录用途更广泛,可能包含如persistence.xml、beans.xml、ejb-jar.xml等更多特定于技术的配置文件。

因此,META-INF目录是JAR文件的一个重要组成部分,用于存储JAR包的元数据和配置信息,并且是Java平台中约定俗成用于此目的的目录。文章来源地址https://www.toymoban.com/news/detail-750826.html

到了这里,关于MapStruct原理解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • GPT关键词挖掘,自动关键词文章生成

    随着互联网的发展,内容营销已成为企业营销策略中不可或缺的一环。有效的文章生成可以帮助企业吸引更多的潜在客户,提高品牌曝光度和转化率,从而实现营销目标。 文章生成是指根据特定的和主题,使用软件工具自动生成相关的文章内容。与传统的

    2024年02月01日
    浏览(40)
  • 实现同时查找多个关键词——KeywordCrafter - 关键词匠心

    具体功能:同时查找多个,高亮加粗显示,并显示出现次数。 🧐碎碎念:最近在写文案的时候,总是要避免出现一个敏感词汇,利用 (command+F) or (Ctr+F) 查找,只能一个一个单词去查,很麻烦。🤷‍♂️ 所以我写了一个简单的网页,在文本框输入一整篇文章,在

    2024年02月13日
    浏览(52)
  • 长尾关键词挖掘软件-免费的百度搜索关键词挖掘

    嗨,大家好!今天,我想和大家聊一聊长尾挖掘工具。作为一个在网络世界里摸爬滚打多年的人,我对这个话题有着一些个人的感悟和见解,希望能与大家分享。 首先,让我坦白一点,长尾挖掘工具对于我来说真是救命稻草。在我刚开始做网站优化和内容创作的

    2024年02月09日
    浏览(74)
  • 关键词生成器在线-在线免费关键词生成器

    生成,什么是生成,生成就是根据你输入的一个生成成千上百的核心,围绕着你输入的核心词来生成的,优先生成大量用户搜索的,今天就给大家分享一款免费生成工具,生成的来源主要是用户都在搜索的词,相关搜索的

    2024年02月04日
    浏览(122)
  • 网站SEO关键词规划时如何筛选出合适的关键词?

    在网站SEO优化过程中,布局是一个至关重要的环节。首先,我们需要确定核心,然后通过各种策略和方法对进行扩展。完成扩展后,接下来的任务就是对这些扩展后的进行筛选。那么,如何进行有效的筛选呢?我们通常建议选择那些具有

    2024年04月17日
    浏览(63)
  • 关键词提取 | 基于Textrank算法的两种关键词提取

    目录 一、PageRank算法 二、TextRank算法 1. 抽取(keyword extraction) 2. 关键短语抽取(keyphrase extration) 3. 关键句抽取(sentence extraction) 三、TextRank算法实现 1. 基于Textrank4zh的TextRank算法实现 2. 基于jieba的TextRank算法实现 3. 基于SnowNLP的TextRank算法实现 四、PageRank算法与Text

    2024年04月14日
    浏览(66)
  • Stable Diffusion 告别猜关键词,LoRA适配关键词自动生成

    有没有想想过在SD绘图的时候下载好的LoRA模型选择之后不生效是为什么?或者说不知道怎么填写? 这里介绍基于 Civitai 的LoRA 使用方法。 如果没有安装的小伙伴可以参考前面的文章先对 Civitai 的模型管理进行安装和使用,确保你的SD主页已经出现了 Civitai 助手 选项卡。

    2024年02月09日
    浏览(50)
  • 一个AI关键词能卖500块?AI绘画引发研究关键词的商机

    一个AI能卖500块?AI绘画引发研究的商机! 绘画一直被人们看作是视觉艺术的呈现方式。通常情况下,学习绘画需要理解调色、构图和线条等要素。然而,自从AI介入绘画领域后,绘画的\\\"画风\\\"迅速发生了变化。网络上涌现出许多教程,教人如何学习AI绘画的关键

    2024年02月10日
    浏览(42)
  • 长尾词和关键词的区别,长尾关键词最简单最常用的2个​获取方法

        要知道长尾词与的区别就要先了解什么是,什么是长尾词。      什么是呢?     是定义您的内容的想法和主题。     什么是长尾词呢?     长尾词是与相关的,可以带来搜索流量的组合型。     获取长尾的最简单的2个方

    2024年02月11日
    浏览(35)
  • 网站万词霸屏推广系统源码:实现关键词推广,轻松提高关键词排名,带完整的安装部署教程

    现如今,互联网的快速发展,网站推广成为企业网络营销的重要手段。而排名作为网站推广的关键因素,一直备受关注。罗峰给大家分享一款网站万词霸屏推广系统源码,该系统可实现推广,有效提高排名,为企业带来更多流量和潜在客户。 以下是部分代

    2024年01月19日
    浏览(69)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包