MapStruct使用指南以及原理解析

发布时间 2023-12-11 11:53:49作者: 一直深夜吃食的喵

使用指南:https://juejin.cn/post/6956190395319451679
原理解析:https://blog.csdn.net/begefefsef/article/details/126434950
image
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平台中约定俗成用于此目的的目录。