Java Review - MapStruct_使用 Intellij 和 Maven Debug 分析MapStruct实现原理

发布时间:2024年01月05日

Java动态编译、JSR 269 和 MapStruct

  • Java动态编译是指在运行时动态地将Java源代码编译成字节码并加载到Java虚拟机中执行。

  • JSR 269 是Java规范请求的一部分,它定义了一种标准的注解处理器API,允许开发人员在编译时扩展Java编译器的功能。

  • JMapStruct 是一个基于 JSR 269 的Java注解处理器,用于生成类型安全的、高性能的、无依赖的Java bean映射代码。通过定义映射接口和相应的映射方法,MapStruct 在编译时生成这些接口的实现类,从而实现了类型安全的对象映射,避免了手动编写繁琐且容易出错的映射代码。

  • MapStruct 使用注解处理器技术,结合了JSR 269的功能,实现了在编译时生成高效的映射代码,从而提供了更快的执行速度和更好的类型安全性。


JSR 269

JSR 269 Pluggable Annotation Processing API是Java社区规范,它允许开发者扩展Java编译器的注解处理能力。通过实现这个API,开发者可以创建自己的注解处理器,这些处理器可以在Java编译器(javac)运行时被调用,以处理特定的注解。

JSR 269的工作原理

  1. 编译器分析:javac对源代码进行分析,生成一棵抽象语法树(AST)。AST是源代码的抽象表示,其中包含了源代码的结构信息。
  2. 调用注解处理器:在编译过程中,javac会检查源代码中的注解,并根据这些注解调用相应的注解处理器。注解处理器是通过实现JSR 269 API创建的。
  3. 处理器逻辑:注解处理器可以执行自己的逻辑,例如修改AST,生成新的代码,或者进行代码分析。这个阶段,注解处理器可能会根据注解信息生成新的类、方法或字段。
  4. 生成字节码:javac使用修改后的AST生成字节码文件。这些字节码文件是Java程序的机器码表示,可以在JVM上运行。

MapStruct示例

MapStruct是一个代码生成库,它使用注解处理器来生成Java Bean属性映射器实现。MapStruct通过实现JSR 269 API,可以在编译时分析带有特定注解的Java类,并根据这些注解生成属性映射器代码。

例如,当你使用MapStruct注解来标注两个Java Bean类,并希望通过注解处理器生成它们之间的映射代码时,MapStruct的注解处理器就会被javac调用。这个处理器会分析注解,生成映射器的实现代码,然后将这些代码插入到AST中。最终,javac会生成包含映射器实现类的字节码文件。

通过这种方式,MapStruct极大地简化了Java Bean属性映射的实现,开发者不需要手动编写繁琐的映射代码,只需通过简单的注解即可。

总之,JSR 269 API为Java编译器提供了强大的扩展能力,使得开发者可以根据自己的需求在编译时进行代码的生成和修改。MapStruct是这种能力的典型应用,它通过注解处理器在编译时生成属性映射代码,提高了开发效率。

在这里插入图片描述


MappingProcessor

在这里插入图片描述

   <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.5.5.Final</version> <!-- 使用最新版本 -->
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.5.5.Final</version> <!-- 使用最新版本 -->
            <scope>provided</scope>
        </dependency>

在MapStruct的包结构中,有两个主要的包:

  1. org.mapstruct:mapstruct:这个包包含了MapStruct的核心注解,这些注解是用来在接口方法上描述映射规则的。主要的注解包括:
    • @Mapper:用于标记一个接口为MapStruct的映射接口。
    • @Mapping:用于标记接口方法,表明该方法将会进行对象属性的映射。
    • @Source@Target@AfterMapping@BeforeMapping等:这些注解用于更精细地控制映射过程,比如指定源对象属性、目标对象属性、映射前后的操作等。
  2. org.mapstruct:mapstruct-processor:这个包包含了MapStruct的注解处理器,它是用于处理上述注解的逻辑,并在编译期生成实现类。这个处理器会读取带有@Mapper注解的接口,并根据接口方法上的@Mapping等注解来生成具体的映射实现代码。这样,开发者就不需要手动编写映射逻辑,提高了开发效率。

在这里插入图片描述

调试编译期生成的代码

MapStruct使用基于生成器的方法创建类型安全的映射代码,这些代码在编译时生成,那如何调测编译期生成的代码呢? 请继续看

想在IDEA中通过远程调试的方式对Maven项目进行调试。

  1. 切换到POM文件所在路径:

    在终端(命令行界面)中,需要使用cd命令来切换到POM文件所在的目录。

    或者找到pom 右键 如下

在这里插入图片描述

  1. 执行mvnDebug compile:

    在终端中输入以下命令来执行Maven构建并启动调试:

    mvnDebug compile
    

    这里的mvnDebug是Maven的调试模式,它会在编译时启动调试器。确保在执行此命令前已经正确设置了Maven的环境变量。

  2. 在IDEA中配置远程JVM调试:

    打开IDEA,按照以下步骤配置远程JVM调试:

    • 打开"Run" )菜单,选择"Edit Configurations"(编辑配置)。
    • 在左侧列表中选择"Remote JVM Debug"。
    • 在右侧的"Port"(端口)字段中输入8000,因为终端提示已经监听8000端口。
    • 应用更改并关闭配置窗口。

在这里插入图片描述

在这里插入图片描述

  1. 打断点并进行调试:
    • 在IDEA中打开您想要调试的Java文件。
    • 在"JavaCompiler"类的"compile"方法处设置一个断点。
    • 在"AbstractProcessor"类的"init"方法和"MappingProcessor"类的"init"方法处也设置断点。
    • 完成断点设置后,点击IDEA工具栏上的"Debug"(调试)按钮开始调试。

在这里插入图片描述

  1. 注意事项:
    • 如果本地编译的class文件已经是最新编译的,直接点击"Debug"按钮可能不会进入调试状态。这种情况下,需要修改代码,比如修改xxx类的属性,以确保有新的class文件生成,然后再次尝试点击"Debug"按钮。

参考:Mapstruct源码解析- 框架实现原理

在这里插入图片描述

文章来源:https://blog.csdn.net/yangshangwei/article/details/135389783
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。