MapStruct對象映射轉(zhuǎn)換解決Bean屬性拷貝性能問題
簡介
MapStruct 是一個代碼生成器(可以生成對象映射轉(zhuǎn)換的代碼),它基于約定優(yōu)于配置的方法,極大地簡化了 Java bean 類型之間的映射實(shí)現(xiàn)。
生成的映射代碼使用普通的方法調(diào)用,因此速度快、類型安全且易于理解。
適用場景
多層應(yīng)用程序通常需要在不同的對象模型(例如實(shí)體和 DTO)之間進(jìn)行映射。編寫這樣的映射代碼是一項乏味且容易出錯的任務(wù)。MapStruct 旨在通過盡可能地自動化來簡化這項工作。
與其他映射框架相比,MapStruct 在編譯時生成 bean 映射,這確保了高性能,允許快速的開發(fā)人員反饋和徹底的錯誤檢查。
說白了就解決 beanCopy 的問題。
工作時機(jī)
MapStruct 是一個注解處理器,它插入到 Java 編譯器中,可用于命令行構(gòu)建(Maven、Gradle 等)以及您首選的 IDE。
MapStruct 使用合理的默認(rèn)值,但在配置或?qū)崿F(xiàn)特殊行為時會采取措施。
使用案例
1、添加依賴
// mapstruct implementation 'org.mapstruct:mapstruct:1.4.2.Final' annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final' 復(fù)制代碼
2、定義兩個類
一個 Car 類(JPA 實(shí)體類)
一個 CarDto 類(數(shù)據(jù)傳輸類)
這兩個類型非常相似,只是在計數(shù)屬性的字段名不同,并且 type 屬性是 CarType 枚舉類型,CarDto 中是字符串類型。
Car 類
public class Car {
private String make;
private int numberOfSeats;
private CarType type;
//constructor, getters, setters etc.
}
CarType 類定義
public enum CarType {
SEDAN;
}
CarDto 類
public class CarDto {
private String make;
private int seatCount;
private String type;
//constructor, getters, setters etc.
}
創(chuàng)建轉(zhuǎn)換器類接口,定義需要將 Car 對象轉(zhuǎn)換為 CarDto 對象
@Mapper
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
@Mapping(source = "numberOfSeats", target = "seatCount")
CarDto carToCarDto(Car car);
}1). @Mapper 注解將該接口標(biāo)記為映射接口,并且讓 MapStruct 處理器在編譯期間進(jìn)行處理,實(shí)際映射方法為 carToCarDto 目的就是原參數(shù)Car,轉(zhuǎn)換為方法返回結(jié)果對象 CarDto
2). 對于源對象和目標(biāo)對象中有不同的屬性名稱,我們可以使用 @Mapping 注解進(jìn)行映射。在默認(rèn)情況下,將源對象和目標(biāo)對象據(jù)歐不同的類型屬性執(zhí)行類型轉(zhuǎn)換,例如,type 數(shù)據(jù)原來是枚舉,可以自動轉(zhuǎn)換為字符串。
3). 以一個 Mapper 接口也支持多個映射方法。所有的這些方法都由 MapStruct 框架來實(shí)現(xiàn)。我們可以從 Mappers類中檢索接口實(shí)現(xiàn)的實(shí)例。通常我們在接口中申明一個 INSTANCE 屬性,提供對外訪問的實(shí)例。
3、單元測試
@Test
public void shouldMapCarToDto () {
//given
Car car = new Car("Morris", 5, CarType.SEDAN);
//when
CarDto carDto = CarMapper.INSTANCE.carToCarDto(car);
//then
assertThat(carDto).isNotNull();
assertThat(carDto.getMake()).isEqualTo("Morris");
assertThat(carDto.getSeatCount()).isEqualTo(5);
assertThat(carDto.getType()).isEqualTo("SEDAN");
}
我們使用起來就是非常簡單,運(yùn)行結(jié)果如下:

核心總結(jié)
MapStruct其實(shí)和 Lombok 有些類似,也是通過插件的方式在我們編譯期為我們生成一些輔助的代碼。但是MapStruct 專注是解決 BeanCopy 以及對象轉(zhuǎn)換的場景。
下面我們看看,就是我們 CarMapper 的實(shí)現(xiàn)類 CarMapperImpl , 這些都是框架在編譯期間,我們生成的代碼。

如果我們使用 BeanUtils.copyProperties來做對象的轉(zhuǎn)換是需要通過反射來獲取對象的屬性,方法等信息。然后再去賦值。反射雖然能夠解決一些通用性的場景,但是對于頻繁的 List 復(fù)制,性能是不高的。我們可以看看下面copyProperties的部分代碼截圖:

個人覺得 MapStruct的優(yōu)勢還是非常明顯的,就是幫助我們少寫了非常多的 getters, setters 進(jìn)行對象的相互轉(zhuǎn)換,性能高于任何一種屬性復(fù)制。缺點(diǎn)就會降低程序編譯速度,增加轉(zhuǎn)換層提升代碼復(fù)雜度。
參考文檔
以上就是MapStruct對象映射轉(zhuǎn)換解決Bean屬性拷貝性能問題的詳細(xì)內(nèi)容,更多關(guān)于MapStruct解決Bean屬性拷貝的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java以struts2為例介紹如何實(shí)現(xiàn)圖片上傳
這篇文章主要介紹了Java struts2中如何實(shí)現(xiàn)圖片上傳的相關(guān)資料,需要的朋友可以參考下2015-11-11
解決mybatis竟然報Invalid value for getInt()的問題
使用mybatis遇到一個非常奇葩的問題,總是報Invalid value for getInt()的問題,怎么解決呢?下面小編通過場景分析給大家代來了mybatis報Invalid value for getInt()的解決方法,感興趣的朋友參考下吧2021-10-10
Java實(shí)現(xiàn)選擇排序算法的實(shí)例教程
這篇文章主要介紹了Java實(shí)現(xiàn)選擇排序算法的實(shí)例教程,選擇排序的時間復(fù)雜度為О(n²),需要的朋友可以參考下2016-05-05
詳解Java實(shí)現(xiàn)JSONArray轉(zhuǎn)Map的三種實(shí)現(xiàn)方式
本文主要介紹了Java實(shí)現(xiàn)JSONArray轉(zhuǎn)Map的三種實(shí)現(xiàn)方式,本文只是自己常用的三種,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03
Java?Collection接口中的常用方法總結(jié)
這篇文章將大概用代碼案例簡單總結(jié)一下?Collection?接口中的一些方法,我們會以他的實(shí)現(xiàn)類?Arraylist?為例創(chuàng)建對象。快一起來看看吧2022-12-12
攔截Druid數(shù)據(jù)源自動注入帳密解密實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了攔截Druid數(shù)據(jù)源自動注入帳密解密實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Java如何實(shí)現(xiàn)圖片裁剪預(yù)覽功能
通常注冊賬戶上傳用戶圖像時需要進(jìn)行預(yù)覽,這篇文章就是教我們?nèi)绾斡?Java 實(shí)現(xiàn)圖片裁剪預(yù)覽功能,需要的朋友可以參考下2015-07-07

