mapStruct由懵逼到入门

工作当中用到了mapStruct, 刚刚使用不求甚解, 仿照同事的代码贴个标签就用起来了, 但其实一点都不懂。下面记录一下由傻逼到入门的知识接收记录。

(190527-0609)

一. mapStruct简单使用

mapStruct用在由DO向DTO转换,或者其他什么两个对象之间的属性拷贝。

过程

  1. 先写一个转换接口,定义一下转换的接口方法(入参是被转化对象,出参是转化成为的对象)。

  2. 把接口贴上个标签,引入maven包,就会在编译时候自动生成转换接口的实现类,把两个对象相同的属性copy的实现方法。

代码

1. pom文件中引入maven包
    <properties>
        <org.mapstruct.version>1.3.0.Final</org.mapstruct.version>
    </properties>
    <dependencies>
        <!--引入mapStruct注解包-->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>
        <!-- mapStruct的annotation processors(下面说,可以理解为编译时生成实现类代码的类)-->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${org.mapstruct.version}</version>
            <scope>provided</scope>
        </dependency>
        <!--谷歌的一个spi包,看作是工具包就好(下面说spi)-->
        <dependency>
            <groupId>com.google.auto.service</groupId>
            <artifactId>auto-service</artifactId>
            <version>1.0-rc5</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!--maven编译默认5.0,使用maven-compiler-plugin插件指定jdk版本,1.6以上-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version> <!-- or newer version -->
                <configuration>
                    <source>1.8</source> <!-- depending on your project -->
                    <target>1.8</target> <!-- depending on your project -->
                    <annotationProcessorPaths>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>
2. 定义转换接口
import cn.gasin.domain.Car;
import cn.gasin.dto.CarDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
/**
* 转换接口
*/
@Mapper
public interface CarMapper {
	//1.定义的实例
	CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
	//2.贴上映射标签的转换接口方法,标签内的值是源属性名和目标属性名不同时候添加的
	@Mapping(source = "numberOfSeats", target = "seatCount")
	CarDto carToCarDto(Car car);
}
3. maven编译,生成实现类

在这里插入图片描述=
在这里插入图片描述

二、 mapStruct的工作原理

mapStruct利用jdk1.6的注解处理器,在编译时候拿到Mapper注解的接口,生成属性拷贝的实现类代码。

过程:

1. mapStruct继承abstructProcessor实现MappingProcessor编译时注解处理器,重写process方法。在其中处理编译时候生成代码的业务

在这里插入图片描述
在这里插入图片描述

2. 在META-INF文件夹下的services文件夹下创建一个Processer接口全限定名的文件,把实现类MappingProcessor的全限定名贴上去,这是SPI(Service Provider Interface)的用法, 它可以发现我们的注解处理器

在这里插入图片描述

3. 总结: 在编译时候,java发现Processor后,生成mappingProcessor对象,每个被编译的类都经过process方法,mapStruct在其中拦截处理,如果是mapper接口的话就按照规则生成转换接口的实现类。

名词介绍:

1. annotation 注解

​ 注解是在源文件中嵌入的Java元数据(附加信息),这些元数据不算是我们的代码,是一些传递给Java的信息(我们也可以拿到这些信息)。是一种类型,类似enum,就是告诉java这个类只能有这几个对象,annotation贴在哪里(类/方法/字段)就是告诉java这个类/方法/字段有啥不一样的标签。

这里可以看一下注解的定义和怎么简单写&用一个注解

知道了注解是什么,也就可以想一两个用法。

​ 比方说mapStruct里面,它就是在编译时候拿到了自己的@Mapper注解(怎么拿到下面说),拿到了注解后就知道了源类和目标类。然后通过反射拿到属性,同名的属性互相拷贝。不同名的属性根据@Mapping注解的source和target进行拷贝。。。(还有很多高级的功能,我不太清楚)

​ Spring里面的注解配置,都是拿到注解信息后进行的。

2. processor 注解处理器

​ javax.annotation.processing.Processor 接口是JDK1.6提供的专门编译时处理注解的接口,继承它,就可以在编译时候在processing方法种拿到想要处理的注解。

注解处理器的详解看这里

对于mapStruct,在编译时后就拿到@Mapper注解信息和注解贴在的接口,然后生成转换的实现类。

3. SPI 服务发现

​ java.util.ServiceLoader进行服务实现的发现与实例化,和反射类似,属于运行时的动态技术,在运行时候使用ServiceLoader拿到接口的实现类。

​ 使用对应库Jar包中需要在META-INF/services下放入名称为接口Api完整类名的文件,并填入对应实现类名(如Jar包内有多个实现,则用换行进行分隔)

Processor和SPI没什么关系,Javac进行注解处理的时候,也使用了SPI技术

SPI简单实用介绍

三、 不懂的地方

1. SPI和processor是怎么协调工作的?

2. SPI如果同一个服务下有多个实例,该怎么办?

TODO 计划下周(190610-16)了解上面两个问题, 并查看一下MyBatis的源码

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值