一、Object mapping 的技術分類:
運行期 反射調用set/get 或者是直接對成員變量賦值 。 該方式通過invoke執行賦值 *,實現時一般會採用beanutil, Javassist等開源庫。這類的代表:Dozer,ModelMaper
編譯期 動態生成set/get代碼的class文件 ,在運行時直接調用該class文件。* 該方式實際上扔會存在set/get代碼,只是不需要自己寫了。 這類的代表:MapStruct,Selma,Orika ### 主要框架性能對比: 每秒鐘執行的object mapping越多越好。
明顯可以看出通過在運行期進行反射的方式執行,性能遠不如編譯器生成class的方式;
MapStruct 與 Selma的對比: https://java.libhunt.com/project/mapstruct/vs/selma
與 ModelMapper的對比:https://java.libhunt.com/project/mapstruct/vs/modelmapper
綜合比較性能、問題排查、文檔、成熟度、擴展性等因素來考慮,MapStruct 是一個不錯的選擇;
二、Maven依賴與配置:
<properties>
<java.version>1.8</java.version>
<org.mapstruct.version>1.2.0.Final</org.mapstruct.version>
</properties>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${java.encoding}</encoding>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
或者可以兩個都寫成依賴,不需要寫成maven插件的形式,後面的依賴用於生成運行期的class實現類,如下:
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
<scope>provided</scope>
</dependency>
三、MapStruct的基本使用:
@Mapper(componentModel = "spring")
public interface MonitorAppGroupIdcDTOMapper {
MonitorAppGroupIdcDTOMapper MAPPER = Mappers.getMapper(MonitorAppGroupIdcDTOMapper.class);
void mapping(MonitorAppGroupIdcDTO source, @MappingTarget MonitorAppGroupIdcDTO dest);
}
編譯後生成的部分代碼結構:
@Component
public class MonitorAppGroupIdcDTOMapperImpl implements MonitorAppGroupIdcDTOMapper {
public MonitorAppGroupIdcDTOMapperImpl() {
}
public void mapping(MonitorAppGroupIdcDTO source, MonitorAppGroupIdcDTO dest) {
if(source != null) {
dest.setId(source.getId());
dest.setGmtCreate(source.getGmtCreate());
...
}
}
}
可以看出MapStruct還需要依賴對象的get/set方法,有時候編寫一堆的get/set方法看上去很不美觀,期望能通過自動生成的方式插入get/set方法,其解決方案是使用lombok。mapstrcut官網也有二者結合的例子: https://github.com/mapstruct/mapstruct/issues/510 Lombok帶來的問題是,如果我們期望通過公有的get/set方法範圍私有屬性時,IDE會提示方法不存在,這個時候我們可以下載安裝Intellij Idea中的”Lombok plugin”來解決,但是這種方案帶來了一定的繁瑣性。比較好的方式是,對於DO或者DTO中的屬性,如果屬性爲私有屬性,需要通過get/set方法來訪問的,那麼就手工生成get/set方法,如果屬性本身爲共有屬性的,那麼就可以藉助Lombok來自動生成get/set方法了。
四、MapStruct的屬性與方法:
- @Mapper註解的componentModel屬性
componentModel 屬性用於指定自動生成的接口實現類的組件類型。這個屬性支持四個值:
default: 這是默認的情況,mapstruct不使用任何組件類型, 可以通過Mappers.getMapper(Class)方式獲取自動生成的實例對象。
cdi: the generated mapper is an application-scoped CDI bean and can be retrieved via @Inject
spring: 生成的實現類上面會自動添加一個@Component註解,可以通過Spring的 @Autowired方式進行注入
jsr330: 生成的實現類上會添加@javax.inject.Named 和@Singleton註解,可以通過 @Inject註解獲取。
五、下面我們先來看下代碼,多對象映射如下所示:
@Mapper(componentModel = "spring")
//@Mapper
public interface GoodInfoMapper
{
//public static GoodInfoMapper MAPPER = Mappers.getMapper(GoodInfoMapper.class);
@Mappings({
@Mapping(source = "type.name",target = "typeName"),
@Mapping(source = "good.id",target = "goodId"),
@Mapping(source = "good.title",target = "goodName"),
@Mapping(source = "good.price",target = "goodPrice")
})
public GoodInfoDTO from(GoodInfoBean good, GoodTypeBean type);
}
原文地址 https://blog.csdn.net/paincupid/article/details/71247255