MapStruct 代替BeanUtil 和ModelMapper

一、Object mapping 的技術(shù)分類:

  1. 運(yùn)行期 反射調(diào)用set/get 或者是直接對(duì)成員變量賦值 。 該方式通過(guò)invoke執(zhí)行賦值,實(shí)現(xiàn)時(shí)一般會(huì)采用beanutil, Javassist等開源庫(kù)。這類的代表:Dozer,ModelMaper
  2. 編譯期 動(dòng)態(tài)生成set/get代碼的class文件 ,在運(yùn)行時(shí)直接調(diào)用該class文件。該方式實(shí)際上扔會(huì)存在set/get代碼,只是不需要自己寫了。 這類的代表:MapStruct,Selma,Orika ### 主要框架性能對(duì)比: 每秒鐘執(zhí)行的object mapping越多越好。
image

明顯可以看出通過(guò)在運(yùn)行期進(jìn)行反射的方式執(zhí)行,性能遠(yuǎn)不如編譯器生成class的方式;

MapStruct 與 Selma的對(duì)比: https://java.libhunt.com/project/mapstruct/vs/selma

MapStruct 與 ModelMapper的對(duì)比: https://java.libhunt.com/project/mapstruct/vs/modelmapper

綜合比較性能、問(wèn)題排查、文檔、成熟度、擴(kuò)展性等因素來(lái)考慮,MapStruct 是一個(gè)不錯(cuò)的選擇;

二、Maven依賴與配置:

 <dependencies>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-jdk8</artifactId>
            <version>1.2.0.CR1</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.2.0.CR1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version> <!-- or newer version -->
                <configuration>
                    <source>1.8</source> <!-- depending on your project -->
                    <target>1.8</target> <!-- depending on your project -->
                </configuration>
            </plugin>
        </plugins>
    </build>

三、MapStruct的基本使用:

//DO  實(shí)體對(duì)象
public class Car {

    private String make;
    private int numberOfSeats;
    private String type;
// get/set .....
}

//DTO 傳輸對(duì)象
public class CarDto {
    private String make;
    private int seatCount;
    private String type;
  // get/set......
}

@Mapper
public interface CarMapper {

    CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
    /**
     * The actual mapping method  expects the source object as parameter and returns the target object.
     * Its name can be freely chosen.
     * 入?yún)ⅲ涸磳?duì)象
     * 返回:轉(zhuǎn)換目標(biāo)對(duì)象
     * 方法名不限制
     */
    @Mapping(source = "numberOfSeats", target = "seatCount")
    CarDto carToCarDto(Car car);
}

// 測(cè)試類
public class MapStructDemo {

    public static void main(String[] args) {
        //given
        Car car = new Car( "Morris", 5, "SENAD" );
        //when
        CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
        System.out.println(carDto);
    }
}

編譯后生成的部分代碼結(jié)構(gòu):

public class CarMapperImpl implements CarMapper {
    public CarMapperImpl() {
    }

    public CarDto carToCarDto(Car car) {
        if (car == null) {
            return null;
        } else {
            CarDto carDto = new CarDto();
            carDto.setSeatCount(car.getNumberOfSeats());
            carDto.setMake(car.getMake());
            carDto.setType(car.getType());
            return carDto;
        }
    }
}

可以看出MapStruct還需要依賴對(duì)象的get/set方法,有時(shí)候編寫一堆的get/set方法看上去很不美觀,期望能通過(guò)自動(dòng)生成的方式插入get/set方法,其解決方案是使用lombok。mapstrcut官網(wǎng)也有二者結(jié)合的例子: https://github.com/mapstruct/mapstruct/issues/510 Lombok帶來(lái)的問(wèn)題是,如果我們期望通過(guò)公有的get/set方法范圍私有屬性時(shí),IDE會(huì)提示方法不存在,這個(gè)時(shí)候我們可以下載安裝Intellij Idea中的”Lombok plugin”來(lái)解決,但是這種方案帶來(lái)了一定的繁瑣性。比較好的方式是,對(duì)于DO或者DTO中的屬性,如果屬性為私有屬性,需要通過(guò)get/set方法來(lái)訪問(wèn)的,那么就手工生成get/set方法,如果屬性本身為共有屬性的,那么就可以借助Lombok來(lái)自動(dòng)生成get/set方法了。

四、MapStruct的屬性與方法:

1. @Mapper注解的componentModel屬性

componentModel 屬性用于指定自動(dòng)生成的接口實(shí)現(xiàn)類的組件類型。這個(gè)屬性支持四個(gè)值:

  • default: 這是默認(rèn)的情況,mapstruct不使用任何組件類型, 可以通過(guò)Mappers.getMapper(Class)方式獲取自動(dòng)生成的實(shí)例對(duì)象。
  • cdi: the generated mapper is an application-scoped CDI bean and can be retrieved via @Inject
  • spring: 生成的實(shí)現(xiàn)類上面會(huì)自動(dòng)添加一個(gè)@Component注解,可以通過(guò)Spring的 @Autowired方式進(jìn)行注入
  • jsr330: 生成的實(shí)現(xiàn)類上會(huì)添加@javax.inject.Named 和@Singleton注解,可以通過(guò) @Inject注解獲取。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 定義注解 Kotlin使用 annotation class 關(guān)鍵字(就像使用 enum class 定義枚舉類一...
    凌寒天下獨(dú)自舞閱讀 1,036評(píng)論 0 0
  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說(shuō)閱讀 12,513評(píng)論 6 13
  • 在面向?qū)ο缶幊讨斜夭豢缮傩枰诖a中定義對(duì)象模型,而在基于Java的業(yè)務(wù)平臺(tái)開發(fā)實(shí)踐中尤其如此。相信大家在平時(shí)開發(fā)...
    消失er閱讀 12,949評(píng)論 15 150
  • 一.概覽 整體描述 dubbo利用spi擴(kuò)展機(jī)制實(shí)現(xiàn)大量的動(dòng)態(tài)擴(kuò)展,要想充分了解dubbo的擴(kuò)展機(jī)制,首先必須弄明...
    致慮閱讀 966評(píng)論 0 2
  • “我就是我,顏色不一樣的煙火,海闊天空,要做最堅(jiān)強(qiáng)的泡沫?!薄窒?若你常被貼上“不食人間煙火”、“不合群”的標(biāo)...
    Sharyn_f057閱讀 195評(píng)論 0 0

友情鏈接更多精彩內(nèi)容