背景
我们在java中复制对象属性一般用ObjectMapper、beanUtils等来复制属性,这样做很方便,但是在底层逻辑上用到的是序列化、反射等原理。这种方式实现总归是不如通过手写getter/setter效率来的高。
但是实现人工书写getter/setter面对多属性的大对象的时候难免显得有些臃肿且不好维护,于是引入主人公mapStruct来。mapStruct通过注解的方式配置实现对象复制,非常的方便。
复制代码
使用
pom依赖
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.0.Beta1</version>
</dependency>
复制代码
官网有个小例子可以看下:
第一步是创建两个需要互相复制的对象; 第二步是通过注解标识方法为对象复制方法; 第三步是调用方式;
使用方式非常清晰明了,他是怎么做到的呢,令人寻味。
原理
- 通过注解标识这是个mapStruct类;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper
public interface CarMapper {
@Mapping(source = "numberOfSeats", target = "seatCount")
CarDto carToCarDto(Car car);
}
复制代码
- 编译时会编译出CarMapper的实现类,对象复制方法完全用getter/setter方法实现;
- 使用时获取carmapper的实现类 carMapperImpl;
CarMapper mapper = Mappers.getMapper(CarMapper.class);
复制代码
实现类是怎么生成出来的呢?
问题的答案在mapstruct-processor 这个依赖里面:
mapstucit-processor通过SPI的方式,
在META-INF/services目录中定义javax.annotation.processing.Processor的实现类org.mapstruct.app.MappingProcessor
依据JSP269协议,MappingProcessor实现了Processor接口中的process方法,根据注解生成了mapper的实现类;