<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          還在用 BeanUtils來做對象轉(zhuǎn)換嗎?快試試 MapStruct吧

          共 4825字,需瀏覽 10分鐘

           ·

          2020-12-30 17:01

          第一次看到?MapStruct?的時候, 我個人非常的開心。因為其跟我內(nèi)心里面的想法不謀而合。

          1 MapStruct 是什么?

          1.1 JavaBean 的困擾

          對于代碼中?JavaBean之間的轉(zhuǎn)換, 一直是困擾我很久的事情。

          在開發(fā)的時候我看到業(yè)務(wù)代碼之間有很多的?JavaBean?之間的相互轉(zhuǎn)化, 非常的影響觀感, 卻又不得不存在。我后來想的一個辦法就是通過反射, 或者自己寫很多的轉(zhuǎn)換器。

          第一種通過反射的方法確實比較方便, 但是現(xiàn)在無論是?BeanUtils,?BeanCopier?等在使用反射的時候都會影響到性能。雖然我們可以進行反射信息的緩存來提高性能。

          但是像這種的話, 需要類型和名稱都一樣才會進行映射, 有很多時候, 由于不同的團隊之間使用的名詞不一樣, 還是需要很多的手動 set/get 等功能。

          第二種的話就是會很浪費時間, 而且在添加新的字段的時候也要進行方法的修改。不過, 由于不需要進行反射, 其性能是很高的。

          1.2?MapStruct?帶來的改變

          MapSturct?是一個生成類型安全, 高性能且無依賴的?JavaBean?映射代碼的注解處理器(annotation processor)。

          抓一下重點:

          1. 注解處理器

          2. 可以生成?JavaBean?之間那的映射代碼

          3. 類型安全, 高性能, 無依賴性

          從字面的理解, 我們可以知道, 該工具可以幫我們實現(xiàn)?JavaBean?之間的轉(zhuǎn)換, 通過注解的方式。

          同時, 作為一個工具類,相比于手寫, 其應(yīng)該具有便捷, 不容易出錯的特點。

          2?MapStruct?入門

          入門很簡單。我是基于?Maven?來進行項目 jar 包管理的。

          2.1 引入依賴


          ????????1.3.0.Final



          ????org.mapstruct
          ????mapstruct-jdk8
          ????${org.mapstruct.version}



          ????org.mapstruct
          ????mapstruct-processor
          ????${org.mapstruct.version}

          2.2?創(chuàng)建entity和dto對象

          該類是從 github 某個訂單系統(tǒng)里面拿下來的部分。

          @Data
          public?class?Order?{

          ????/**
          ?????*訂單id
          ?????*/
          ????private?Long?id;

          ????/**
          ?????*?訂單編號
          ?????*/
          ????private?String?orderSn;

          ????/**
          ?????*?收貨人姓名/號碼
          ?????*/
          ????private?String?receiverKeyword;

          ????/**
          ?????*?訂單狀態(tài):0->待付款;1->待發(fā)貨;2->已發(fā)貨;3->已完成;4->已關(guān)閉;5->無效訂單
          ?????*/
          ????private?Integer?status;

          ????/**
          ?????*?訂單類型:0->正常訂單;1->秒殺訂單
          ?????*/
          ????private?Integer?orderType;

          ????/**
          ?????*?訂單來源:0->PC訂單;1->app訂單
          ?????*/
          ????private?Integer?sourceType;
          }

          對應(yīng)的查詢參數(shù)

          @Data
          public?class?OrderQueryParam?{
          ????/**
          ?????*?訂單編號
          ?????*/
          ????private?String?orderSn;

          ????/**
          ?????*?收貨人姓名/號碼
          ?????*/
          ????private?String?receiverKeyword;

          ????/**
          ?????*?訂單狀態(tài):0->待付款;1->待發(fā)貨;2->已發(fā)貨;3->已完成;4->已關(guān)閉;5->無效訂單
          ?????*/
          ????private?Integer?status;

          ????/**
          ?????*?訂單類型:0->正常訂單;1->秒殺訂單
          ?????*/
          ????private?Integer?orderType;

          ????/**
          ?????*?訂單來源:0->PC訂單;1->app訂單
          ?????*/
          ????private?Integer?sourceType;


          }

          2.3?寫 Mapper

          Mapper?即映射器, 一般來說就是寫?xxxMapper?接口。

          當(dāng)然, 不一定是以?Mapper?結(jié)尾的。只是官方是這么寫的。在本入門例子中,對應(yīng)的接口如下

          import?com.homejim.mapstruct.dto.OrderQueryParam;
          import?com.homejim.mapstruct.entity.Order;
          import?org.mapstruct.Mapper;
          import?org.mapstruct.Mapping;

          @Mapper
          public?interface?OrderMapper?{

          ????OrderQueryParam?entity2queryParam(Order?order);

          }

          簡單的映射(字段和類型都匹配), 只有一個要求, 在接口上寫?@Mapper?注解即可。

          然后方法上, 入?yún)?yīng)要被轉(zhuǎn)化的對象, 返回值對應(yīng)轉(zhuǎn)化后的對象, 方法名稱可任意。

          2.4 測試

          寫一個測試類測試一下。

          @Test
          public?void?entity2queryParam()?{
          ????Order?order?=?new?Order();
          ????order.setId(12345L);
          ????order.setOrderSn("orderSn");
          ????order.setOrderType(0);
          ????order.setReceiverKeyword("keyword");
          ????order.setSourceType(1);
          ????order.setStatus(2);

          ????OrderMapper?mapper?=?Mappers.getMapper(OrderMapper.class);
          ????OrderQueryParam?orderQueryParam?=?mapper.entity2queryParam(order);
          ????assertEquals(orderQueryParam.getOrderSn(),?order.getOrderSn());
          ????assertEquals(orderQueryParam.getOrderType(),?order.getOrderType());
          ????assertEquals(orderQueryParam.getReceiverKeyword(),?order.getReceiverKeyword());
          ????assertEquals(orderQueryParam.getSourceType(),?order.getSourceType());
          ????assertEquals(orderQueryParam.getStatus(),?order.getStatus());

          }

          測試通過, 沒有任何的問題。

          3 MapStruct 分析

          上面中, 我寫了3個步驟來實現(xiàn)了從?Order?到?OrderQueryParam?的轉(zhuǎn)換。

          那么, 作為一個注解處理器, 通過MapStruct?生成的代碼具有怎么樣的優(yōu)勢呢?

          3.1 高性能

          這是相對反射來說的, 反射需要去讀取字節(jié)碼的內(nèi)容, 花銷會比較大。

          而通過?MapStruct?來生成的代碼, 其類似于人手寫。速度上可以得到保證。

          前面例子中生成的代碼可以在編譯后看到。在 target/generated-sources/annotations 里可以看到。

          生成的代碼

          對應(yīng)的代碼

          @Generated(
          ????value?=?"org.mapstruct.ap.MappingProcessor",
          ????date?=?"2019-08-02T00:29:49+0800",
          ????comments?=?"version:?1.3.0.Final,?compiler:?javac,?environment:?Java?11.0.2?(Oracle?Corporation)"
          )
          public?class?OrderMapperImpl?implements?OrderMapper?{

          ????@Override
          ????public?OrderQueryParam?entity2queryParam(Order?order)?{
          ????????if?(?order?==?null?)?{
          ????????????return?null;
          ????????}

          ????????OrderQueryParam?orderQueryParam?=?new?OrderQueryParam();

          ????????orderQueryParam.setOrderSn(?order.getOrderSn()?);
          ????????orderQueryParam.setReceiverKeyword(?order.getReceiverKeyword()?);
          ????????orderQueryParam.setStatus(?order.getStatus()?);
          ????????orderQueryParam.setOrderType(?order.getOrderType()?);
          ????????orderQueryParam.setSourceType(?order.getSourceType()?);

          ????????return?orderQueryParam;
          ????}
          }

          可以看到其生成了一個實現(xiàn)類, 而代碼也類似于我們手寫, 通俗易懂。

          3.2 易于 debug

          在我們生成的代碼中, 我們可以輕易的進行 debug。

          易于 DEBUG

          在使用反射的時候, 如果出現(xiàn)了問題, 很多時候是很難找到是什么原因的。

          3.3 使用相對簡單

          如果是完全映射的, 使用起來肯定沒有反射簡單。用類似?BeanUtils?這些工具一條語句就搞定了。但是,如果需要進行特殊的匹配(特殊類型轉(zhuǎn)換, 多對一轉(zhuǎn)換等), 其相對來說也是比較簡單的。

          基本上, 使用的時候, 我們只需要聲明一個接口, 接口下寫對應(yīng)的方法, 就可以使用了。當(dāng)然, 如果有特殊情況, 是需要額外處理的。

          3.4 代碼獨立

          生成的代碼是對立的, 沒有運行時的依賴。

          作者:阿進的寫字臺
          出處:https://www.cnblogs.com/homejim/
          本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。



          PS:歡迎在留言區(qū)留下你的觀點,一起討論提高。如果今天的文章讓你有新的啟發(fā),歡迎轉(zhuǎn)發(fā)分享給更多人。

          —————END—————


          推薦閱讀:



          最近面試BAT,整理一份面試資料Java面試BAT通關(guān)手冊,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點“在看”,關(guān)注公眾號并回復(fù)?666?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          明天見(??ω??)??
          瀏覽 40
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美三级片中文字幕在线观看 | 日韩网址在线观看 | 18禁网站在线看 | 一级片www | 夜夜无码|