<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>

          Bean 自動(dòng)轉(zhuǎn)換神器 Mapstruct 官方的 Spring 插件真香啊!

          共 856字,需瀏覽 2分鐘

           ·

          2022-05-11 01:05

          《Java 面試指北》來(lái)啦!這是一份教你如何更高效地準(zhǔn)備面試的小冊(cè),涵蓋常見(jiàn)八股文(系統(tǒng)設(shè)計(jì)、常見(jiàn)框架、分布式、高并發(fā) ......)、優(yōu)質(zhì)面經(jīng)等內(nèi)容。

          在幾年前,我就安利過(guò)Mapstruct這個(gè)神器,它可以代替BeanUtil來(lái)進(jìn)行DTOVO、PO之間的轉(zhuǎn)換。它使用的是Java編譯期的 ?annotation processor 機(jī)制,說(shuō)白了它就是一個(gè)代碼生成器,代替你手工進(jìn)行類(lèi)型轉(zhuǎn)換期間的取值賦值操作。


          很多開(kāi)源項(xiàng)目也是用的?Mapstruct 進(jìn)行?DTO、VOPO?等對(duì)象的互轉(zhuǎn),就比如我在幾年分享的??eladmin 這個(gè)開(kāi)源項(xiàng)目:一份熱乎的 SpringBoot 前后端分離后臺(tái)管理系統(tǒng)分析!分模塊開(kāi)發(fā)、RBAC權(quán)限控制...?。


          下面是 Guide 自己記錄的一些筆記:


          我在很多項(xiàng)目都使用了它,代碼清爽得很,增加了大量摸魚(yú)時(shí)間,用過(guò)的都說(shuō)好。

          @Mapper(componentModel?=?"spring")
          public?interface?AreaMapping?{

          ????List?toVos(List?areas);
          }

          就這么幾行就把一個(gè)PO的集合轉(zhuǎn)換成了對(duì)應(yīng)VO的集合。

          //?spring?bean?
          @Autowired
          AreaMapping?areaMapping
          ????
          //?轉(zhuǎn)換源?areas????
          List?areas?=?……;
          //?轉(zhuǎn)換目標(biāo)?vos?
          List?vos?=?areaMapping.toVos(areas)

          換成你手寫(xiě)試試,起碼得五分之一炷香的功夫。

          但是這樣寫(xiě)還是不太爽,每次都要掛對(duì)應(yīng)的Mapper類(lèi)。

          Converter

          Spring framework提供了一個(gè)Converter接口:

          @FunctionalInterface
          public?interface?Converter<S,?T>?{
          ????@Nullable
          ????T?convert(S?source);

          ????default??Converter?andThen(Convertersuper?T,???extends?U>?after)?{
          ????????Assert.notNull(after,?"After?Converter?must?not?be?null");
          ????????return?(s)?->?{
          ????????????T?initialResult?=?this.convert(s);
          ????????????return?initialResult?!=?null???after.convert(initialResult)?:?null;
          ????????};
          ????}
          }

          它的作用是將S轉(zhuǎn)換為T,這和Mapstruct的作用不謀而合。

          Converter會(huì)通過(guò)ConverterRegistry這個(gè)注冊(cè)接口注冊(cè)到ConversionService,然后你就可以通過(guò)ConversionServiceconvert方法來(lái)進(jìn)行轉(zhuǎn)換:

          ?????T?convert(@Nullable?Object?source,?Class?targetType);

          MapStruct Spring Extensions

          根據(jù)上面的機(jī)制官方推出了MapStruct Spring Extensions插件, 它實(shí)現(xiàn)了一種機(jī)制,所有的Mapstruct映射接口(Mapper)只要實(shí)現(xiàn)了Converter,都會(huì)自動(dòng)注冊(cè)到ConversionService,我們只需要通過(guò)ConversionService就能完成任何轉(zhuǎn)換操作。

          /**
          ?*?@author?felord.cn
          ?*?@since?1.0.0
          ?*/

          @Mapper(componentModel?=?"spring")
          public?interface?CarMapper?extends?Converter<Car,?CarDto>?{

          ????@Mapping(target?=?"seats",?source?=?"seatConfiguration")
          ????CarDto?convert(Car?car);
          }

          調(diào)用時(shí):

          @Autowired
          private?ConversionService?conversionService;

          Car?car?=?……;
          CarDto?carDto?=?conversionService.convert(car,CarDto.class);

          MapStruct Spring Extensions?會(huì)自動(dòng)生成一個(gè)適配類(lèi)處理Mapper注冊(cè):

          package?org.mapstruct.extensions.spring.converter;

          import?cn.felord.mapstruct.entity.Car;
          import?cn.felord.mapstruct.entity.CarDto;
          import?org.springframework.context.annotation.Lazy;
          import?org.springframework.core.convert.ConversionService;
          import?org.springframework.stereotype.Component;
          /**
          ?*?@author?felord.cn
          ?*?@since?1.0.0
          ?*/

          @Component
          public?class?ConversionServiceAdapter?{
          ????private?final?ConversionService?conversionService;

          ????public?ConversionServiceAdapter(@Lazy?final?ConversionService?conversionService)?{
          ????????this.conversionService?=?conversionService;
          ????}

          ????public?CarDto?mapCarToCarDto(final?Car?source)?{
          ????????return?(CarDto)this.conversionService.convert(source,?CarDto.class);
          ????}
          }

          自定義

          自定義適配類(lèi)的包路徑和名稱(chēng)

          默認(rèn)情況下,生成的適配類(lèi)將位于包org.mapstruct.extensions.spring.converter中,名稱(chēng)固定為ConversionServiceAdapter。如果你希望修改包路徑或者名稱(chēng),你可以這樣:

          package?cn.felord.mapstruct.config;

          import?org.mapstruct.MapperConfig;
          import?org.mapstruct.extensions.spring.SpringMapperConfig;

          /**
          ?*?@author?felord.cn
          ?*?@since?1.0.0
          ?*/

          @MapperConfig(componentModel?=?"spring")
          @SpringMapperConfig(conversionServiceAdapterPackage?=?"cn.felord.mapstruct.config",
          ????????conversionServiceAdapterClassName?=?"MapStructConversionServiceAdapter")
          public?class?MapperSpringConfig?{
          }
          ?

          不指定conversionServiceAdapterPackage元素,生成的 Adapter 類(lèi)將與注解的 Config 駐留在同一個(gè)包中,所以上面的路徑是可以省略的。

          指定ConversionService

          如果你的Spring IoC容器中有多個(gè)ConversionService,你可以通過(guò)@SpringMapperConfig注解的conversionServiceBeanName?參數(shù)指定。

          package?cn.felord.mapstruct.config;

          import?org.mapstruct.MapperConfig;
          import?org.mapstruct.extensions.spring.SpringMapperConfig;

          /**
          ?*?@author?felord.cn
          ?*?@since?1.0.0
          ?*/

          @MapperConfig(componentModel?=?"spring")
          @SpringMapperConfig(conversionServiceAdapterPackage?=?"cn.felord.mapstruct.config",
          ????????conversionServiceAdapterClassName?=?"MapStructConversionServiceAdapter",
          ???????????????????conversionServiceBeanName?=?"myConversionService")
          public?class?MapperSpringConfig?{
          }

          集成Spring的內(nèi)置轉(zhuǎn)換

          Spring內(nèi)部提供了很多好用的Converter實(shí)現(xiàn),有的并不直接開(kāi)放,如果你想用Mapstruct的機(jī)制使用它們,可以通過(guò)@SpringMapperConfig注解的?externalConversions注冊(cè)它們。

          @MapperConfig(componentModel?=?"spring")
          @SpringMapperConfig(
          ???externalConversions?=?@ExternalConversion(sourceType?=?String.class,?targetType?=?Locale.class))
          public?interface?MapstructConfig?
          {}

          會(huì)在適配器中自動(dòng)生成相應(yīng)的轉(zhuǎn)換:

          @Component
          public?class?ConversionServiceAdapter?{
          ??private?final?ConversionService?conversionService;

          ??public?ConversionServiceAdapter(@Lazy?final?ConversionService?conversionService)?{
          ????this.conversionService?=?conversionService;
          ??}

          ??public?Locale?mapStringToLocale(final?String?source)?{
          ????return?conversionService.convert(source,?Locale.class);
          ??}
          }

          總結(jié)

          mapstruct-spring-annotations?使開(kāi)發(fā)人員能夠通過(guò)ConversionService使用定義的?Mapstruct?映射器,而不必單獨(dú)導(dǎo)入每個(gè)?Mapper,從而允許?Mapper?之間的松散耦合。,它本身不會(huì)影響Mapstruct的機(jī)制。

          項(xiàng)目源碼地址:https://gitee.com/felord/mapstruct-spring-extensions

          ··········? END? ··············

          近期文章精選?:

          如果本文對(duì)你有幫助的話,歡迎點(diǎn)贊&在看&分享,這對(duì)我繼續(xù)分享&創(chuàng)作優(yōu)質(zhì)文章非常重要。感謝????

          瀏覽 149
          點(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>
                  www.操碰 | 操逼视频免费看 | 在线欧美成人网站 | 久久秘 一区二区三区四区 | 肏逼视频免费观看 |