<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來(lái)做對(duì)象轉(zhuǎn)換嗎?快試試 MapStruct吧

          共 8059字,需瀏覽 17分鐘

           ·

          2020-12-07 04:56


          作者:阿進(jìn)的寫(xiě)字臺(tái)

          https://www.cnblogs.com/homejim/

          第一次看到 MapStruct 的時(shí)候, 我個(gè)人非常的開(kāi)心。因?yàn)槠涓覂?nèi)心里面的想法不謀而合。

          1 MapStruct 是什么?

          1.1 JavaBean 的困擾

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

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

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

          但是像這種的話, 需要類(lèi)型和名稱都一樣才會(huì)進(jìn)行映射, 有很多時(shí)候, 由于不同的團(tuán)隊(duì)之間使用的名詞不一樣, 還是需要很多的手動(dòng) set/get 等功能。

          第二種的話就是會(huì)很浪費(fèi)時(shí)間, 而且在添加新的字段的時(shí)候也要進(jìn)行方法的修改。不過(guò), 由于不需要進(jìn)行反射, 其性能是很高的。

          1.2 MapStruct 帶來(lái)的改變

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

          抓一下重點(diǎn):

          1. 注解處理器

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

          3. 類(lèi)型安全, 高性能, 無(wú)依賴性

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

          同時(shí), 作為一個(gè)工具類(lèi),相比于手寫(xiě), 其應(yīng)該具有便捷, 不容易出錯(cuò)的特點(diǎn)。

          2 MapStruct 入門(mén)

          入門(mén)很簡(jiǎn)單。我是基于 Maven 來(lái)進(jìn)行項(xiàng)目 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對(duì)象

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

          @Data
          public class Order {

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

              /**
               * 訂單編號(hào)
               */
              private String orderSn;

              /**
               * 收貨人姓名/號(hào)碼
               */
              private String receiverKeyword;

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

              /**
               * 訂單類(lèi)型:0->正常訂單;1->秒殺訂單
               */
              private Integer orderType;

              /**
               * 訂單來(lái)源:0->PC訂單;1->app訂單
               */
              private Integer sourceType;
          }

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

          @Data
          public class OrderQueryParam {
              /**
               * 訂單編號(hào)
               */
              private String orderSn;

              /**
               * 收貨人姓名/號(hào)碼
               */
              private String receiverKeyword;

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

              /**
               * 訂單類(lèi)型:0->正常訂單;1->秒殺訂單
               */
              private Integer orderType;

              /**
               * 訂單來(lái)源:0->PC訂單;1->app訂單
               */
              private Integer sourceType;


          }

          2.3 寫(xiě) Mapper

          Mapper 即映射器, 一般來(lái)說(shuō)就是寫(xiě) xxxMapper 接口。

          當(dāng)然, 不一定是以 Mapper 結(jié)尾的。只是官方是這么寫(xiě)的。在本入門(mén)例子中,對(duì)應(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);

          }

          簡(jiǎn)單的映射(字段和類(lèi)型都匹配), 只有一個(gè)要求, 在接口上寫(xiě) @Mapper 注解即可。

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

          2.4 測(cè)試

          寫(xiě)一個(gè)測(cè)試類(lèi)測(cè)試一下。

          @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());

          }

          測(cè)試通過(guò), 沒(méi)有任何的問(wèn)題。

          3 MapStruct 分析

          上面中, 我寫(xiě)了3個(gè)步驟來(lái)實(shí)現(xiàn)了從 OrderOrderQueryParam 的轉(zhuǎn)換。

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

          3.1 高性能

          這是相對(duì)反射來(lái)說(shuō)的, 反射需要去讀取字節(jié)碼的內(nèi)容, 花銷(xiāo)會(huì)比較大。而通過(guò) MapStruct 來(lái)生成的代碼, 其類(lèi)似于人手寫(xiě)。速度上可以得到保證。

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

          生成的代碼


          對(duì)應(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;
              }
          }

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

          3.2 易于 debug

          在我們生成的代碼中, 我們可以輕易的進(jìn)行 debug。

          易于 DEBUG


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

          3.3 使用相對(duì)簡(jiǎn)單

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

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

          3.4 代碼獨(dú)立

          生成的代碼是對(duì)立的, 沒(méi)有運(yùn)行時(shí)的依賴。


          --------------------------   END  --------------------------


          原創(chuàng)整理《第2版:互聯(lián)網(wǎng)大廠面試題》



          掃碼添加,我的個(gè)人微信,備注:面試題
           注意,不要亂回復(fù) 
          (一定要備注:面試題)否則不給通過(guò)

          如果被添加頻繁,請(qǐng)30分鐘后再試試

          沒(méi)錯(cuò),加我好友,給你安排到位

          瀏覽 28
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  青青草视频黄色在线观看 | 超碰大香蕉精品国产 | 欧美精品一二三 | 黄片操比 | 欧老太做爱 亚洲性猛交 |