自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

喜新厭舊,是我的本性。今天就寵Mapstruct怎么了!

開發(fā) 后端
這些年寫Java寫多了,感覺Java是越來越丑。尤其是在玩了TypeScript之后,看到Java代碼總有一股想吐的感覺。這種思想的轉(zhuǎn)變,從側(cè)面上證明了,我并不是一個(gè)專一的人。

[[381393]]

本文轉(zhuǎn)載自微信公眾號「小姐姐味道」,作者姐養(yǎng)狗2號 。轉(zhuǎn)載本文請聯(lián)系小姐姐味道公眾號。   

這些年寫Java寫多了,感覺Java是越來越丑。尤其是在玩了TypeScript之后,看到Java代碼總有一股想吐的感覺。這種思想的轉(zhuǎn)變,從側(cè)面上證明了,我并不是一個(gè)專一的人。

因?yàn)槲沂且粭l狗。

喜新厭舊,是我的本性,即使我把自己表現(xiàn)的很純潔。

按理說,牛x的人物并不需要關(guān)注語言層面這種較低級的問題。但是,無論是什么語言,各種屬性拷貝,是在工程上繞不開的問題。比如折騰人的VO、BO、DTO、DO等。

項(xiàng)目中的代碼,有六成,是在做這些無用的轉(zhuǎn)換和各種數(shù)據(jù)驗(yàn)證。這個(gè)比例是我瞎謅的,但也相差無幾。

在Java中,有三種方式來處理這些屬性拷貝:

  1. 直接硬編碼,把代碼硬懟上去
  2. 使用各種BeanUtils,通過反射完成賦值
  3. 使用類似MapStruct的工具,直接在編譯期完成

其實(shí)嘛,哪一種都有利弊,有些東西雖然香,但實(shí)際用起來,還是要思量一下。個(gè)個(gè)打扮的花枝招展的,都是外在的皮囊。

本文主要介紹Mapstruct的使用,并從這香噴噴的工具中,聞一下其中變餿的味道。

1. 如何使用?

照例,需要在pom中加入依賴包,我們這里用的是1.4.1.Final版本。

  1. <dependency> 
  2.     <groupId>org.mapstruct</groupId> 
  3.     <artifactId>mapstruct</artifactId> 
  4.     <version>${org.mapstruct.version}</version> 
  5. </dependency> 

這還沒完,還需要在pom中的build部分,增加一個(gè)插件。搞這么復(fù)雜,是因?yàn)樗脑砗蚻ombok是一樣的,同樣通過APT在編譯器實(shí)現(xiàn)的。

 

這意味著,它的代碼,在編譯期就完成了。不需要反射,所以效率就和直接寫get、set,是一樣的。

  1. <plugin> 
  2.     <groupId>org.apache.maven.plugins</groupId> 
  3.     <artifactId>maven-compiler-plugin</artifactId> 
  4.     <version>3.8.1</version> 
  5.     <configuration> 
  6.         <source>1.8</source> 
  7.         <target>1.8</target> 
  8.         <annotationProcessorPaths> 
  9.             <path> 
  10.                 <groupId>org.mapstruct</groupId> 
  11.                 <artifactId>mapstruct-processor</artifactId> 
  12.                 <version>${org.mapstruct.version}</version> 
  13.             </path> 
  14.             <path> 
  15.                 <groupId>org.projectlombok</groupId> 
  16.                 <artifactId>lombok</artifactId> 
  17.                 <version>1.18.16</version> 
  18.             </path> 
  19.             <path> 
  20.                 <groupId>org.projectlombok</groupId> 
  21.                 <artifactId>lombok-mapstruct-binding</artifactId> 
  22.                 <version>0.2.0</version> 
  23.             </path> 
  24.         </annotationProcessorPaths> 
  25.     </configuration> 
  26. </plugin> 

這時(shí)候,我們就可以使用它提供的注解,方便的進(jìn)行屬性拷貝了。

  1. @Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) 
  2. public interface Transform { 
  3.     Transform T = Mappers.getMapper(Transform.class); 
  4.     Member fromMemberEntity(MemberEntity entity); 
  5.     MemberEntity fromMember(Member member); 

上面是一段示例代碼。Mapper注解,標(biāo)志著這是一個(gè)類型轉(zhuǎn)換工具(對象映射器),它提供了很多策略供我們選擇。直接寫接口文件,并不需要做一些額外的動作,mapstruct就知道你要干什么!

在傳統(tǒng)的編程中,如果Member的屬性非常的多,我們需要手工完成這個(gè)過程,代碼會非常的多。

使用Mapperstruct之后,這部分重復(fù)的勞動,工具都替我們做了。

瞧瞧下面這張圖!

 

上面的圖表明了,代碼在target下的generated-source目錄下生成,這就是我們上面添加的插件的功勞;代碼的內(nèi)容,其實(shí)就是一些非空判斷和get、set等。相同字段名相同類型的屬性,將會無差別的拷貝過去。

如果你的bean屬性非常的多,這個(gè)工具會讓你的代碼由幾百行,變成幾行!

2. 與其他方式比較

那mapstruct有什么優(yōu)勢么?為什么不直接使用BeanUtils?它們的效果一樣的啊,而且后者各種類庫都有提供。

主要原因,就是效率問題。

BeanUtils是通過反射實(shí)現(xiàn)的,效率肯定很低;而mapstuct是基于APT實(shí)現(xiàn)的,沒有性能損耗。

BeanUtils的屬性拷貝,在判斷空值和不同類型的屬性時(shí),有很多障礙,會歇菜;而mapstruct有非常靈活的策略和轉(zhuǎn)化方式,自定義性比較強(qiáng)(后面會談到)。

3. 復(fù)雜場景

那下面我們就來看一個(gè)復(fù)雜的場景。

如果你的bean中,只有一些普通的屬性,那么使用mapstruct,就是如絲般的順滑。但總有一些異常情況,需要使用更高級的處理方式。

假設(shè)我想要由Unit轉(zhuǎn)化為ProductUnitEntity,但其中有個(gè)字段measureType它們的類型不一樣,我們就可以使用Mappings注解完成這個(gè)轉(zhuǎn)化。

  1. @Mappings({ 
  2.             @Mapping(source = "measureType.value", target = "measureType"
  3.     }) 
  4. ProductUnitEntity fromUnit(Unit v); 

編譯后的代碼如下所示。有了source和target,就可以實(shí)現(xiàn)比BeanUtils更加牛x的行為。你甚至可以通過dateFormat做一些日期轉(zhuǎn)化之類的。

 

其實(shí),上面的measureType是一個(gè)枚舉類型。如何將普通的類型轉(zhuǎn)化為枚舉類型呢?我們只需要提供一個(gè)default方法就ok了。mapstruct會判斷參數(shù)類型和返回值,所以說方法的名稱可以是任何合法的值。

  1. default Unit.MeasureType measureTypeIntegerToDomain(Integer value) { 
  2.         for (Unit.MeasureType s : Unit.MeasureType.values()) { 
  3.             if (s.getValue() == value) { 
  4.                 return s; 
  5.             } 
  6.         } 
  7.         return null

那mapstruct能實(shí)現(xiàn)List之間的轉(zhuǎn)化么?也是可以的。下面兩行代碼,就能夠自動的補(bǔ)充for循環(huán),讓你的代碼更加簡潔。

  1. List<StockKeepingUnit> fromSkuEntityList(List<StockKeepingUnitEntity> v); 
  2. List<StockKeepingUnitEntity> fromSkuList(List<StockKeepingUnit> v); 

End那么問題來了。

既然這么好的東西,那為什么現(xiàn)在的很多項(xiàng)目,都不用mapstruct,甚至連BeanUtils都不用,直接手工在那里get、set呢?

一種原因是,這些工具會大幅減少代碼量。mapstruct+hibernate-validate,一個(gè)管轉(zhuǎn)化,另一個(gè)管驗(yàn)證,簡直就是以代碼行數(shù)論天下的公司的噩夢??冃档偷?

另一種原因就是,使用這些工具,并 不利于項(xiàng)目的重構(gòu) 。假如你在DTO里把a(bǔ)字段改成了b字段,mapstruct都貼心的為你忽略了這些變化。你的項(xiàng)目代碼并不會提示錯(cuò)誤,風(fēng)險(xiǎn)將直接帶到運(yùn)行時(shí)。

而使用get、set的方式,除了代碼量變的非常多以外,唯一的風(fēng)險(xiǎn)就是開發(fā)人員忘記了為某個(gè)新增的字段賦值。

在這種情況下,機(jī)器干的活,并不一定比人類可靠。所以使用mapstruct有一個(gè)大的前提:你的團(tuán)隊(duì),能夠通過約定,不給變量亂起名字,不亂重構(gòu)。如此,才能發(fā)揮它的價(jià)值。

作者簡介:小姐姐味道 (xjjdog),一個(gè)不允許程序員走彎路的公眾號。聚焦基礎(chǔ)架構(gòu)和Linux。十年架構(gòu),日百億流量,與你探討高并發(fā)世界,給你不一樣的味道。我的個(gè)人微信xjjdog0,歡迎添加好友,進(jìn)一步交流。

 

責(zé)任編輯:武曉燕 來源: 小姐姐味道
相關(guān)推薦

2018-02-24 23:19:31

iOSbug蘋果

2022-10-31 10:40:07

MySQLPostgreSQL數(shù)據(jù)庫

2011-12-07 10:16:45

Firefox新聞

2019-12-09 11:11:52

LoRaWi-Fi頻段

2009-09-27 10:59:23

UPS系統(tǒng)故障

2010-08-27 10:43:39

馬云

2016-12-02 08:36:33

蘋果三星科技新聞早報(bào)

2023-11-14 07:40:36

阿里云服務(wù)中斷事件

2017-12-25 23:38:42

2022-01-25 10:11:10

紅綠屏蘋果BUG

2012-06-08 09:57:25

2013-05-20 11:29:11

Windows 8

2016-01-27 17:07:52

VMware

2013-05-06 09:19:10

Firefox火狐瀏覽器

2022-04-12 13:30:56

云計(jì)算阿里互聯(lián)網(wǎng)行業(yè)

2011-01-13 10:50:42

AMD

2019-08-12 10:27:34

前端程序員網(wǎng)絡(luò)

2019-03-27 10:54:00

5G運(yùn)營商設(shè)備制造商

2022-05-05 09:23:21

裁員程序員危機(jī)

2023-01-19 00:13:28

代碼技術(shù)計(jì)劃
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號