MapStructPlus 1.4.0 釋出,體積更輕量!效能更強!

林培烈發表於2024-03-17

MapStruct Plus 是 MapStruct 的增強工具,在 Mapstruct 的基礎上,實現了自動生成 Mapper 介面的功能,並強化了部分功能,使 Java 型別轉換更加便捷、優雅。

MapStructPlus官網

此次迎來了一次較大版本的更新,更新日誌如下:

  • 最佳化複雜物件轉換邏輯,佔用元空間更小!效能更快!

此版本針對於複雜物件的自動轉換邏輯,進行了最佳化和部分的重新設計,減少了一些不必要的轉換方法,佔用元空間更小。

RuoYi-Vue-Plus 為例,使用新版本後,元空間佔用減少了 7MB,根據專案的複雜程度不同,減少的記憶體佔用也有所不同。

且根據 issue#67 中提到,在 SpringBoot + Aop 場景下,效能會受影響, 在新版本中,修改了實現方式,效能比提升一半以上。

  • 去除 hutool 等依賴,目前專案中只依賴了 MapStruct

從 1.4.0 版本之後,去除了 MapStruct 之外的依賴,打包後體積更小。

但當需要使用 Map 與物件轉換時,需要額外引入 hutool-core 依賴包。

  • 適配物件迴圈巢狀場景

類迴圈巢狀是指兩個類互相引用,例如,源物件和目標物件結構都包含父物件和子物件之間的雙向關聯。
當存在這種情況時,直接進行轉換時,會導致棧溢位的問題(stack overflow error)。

示例:

@Data
public class TreeNode {
    private TreeNode parent;
    private List<TreeNode> children;
}

@Data
public class TreeNodeDto {
    private TreeNodeDto parent;
    private List<TreeNodeDto> children;
}

parent 屬性可以是其他型別的,可能跨越一個更長的屬性鍊形成的巢狀迴圈。

為了適配這種情況,MapStructPlus 的 AutoMapper 註解中增加了 cycleAvoiding 屬性,該屬性用於標識,是否需要避免迴圈巢狀的問題。
預設為 false,如果需要避免迴圈巢狀,需要將該屬性設定為 true

當配置為 true 時,在整個物件的轉換過程鏈路中,會傳遞一個 CycleAvoidingMappingContext 物件,臨時儲存轉換生成的物件,
在轉換鏈路中,如果發現需要生成的物件已經存在,會直接返回該型別,從而避免棧溢位問題。

以上面的示例為例,在 AutoMapper 註解中,配置 cycleAvoiding 屬性為 true,如下所示:

@Data
@AutoMapper(target = TreeNodeDto.class, cycleAvoiding = true)
public class TreeNode {
    private TreeNode parent;
    private List<TreeNode> children;
}

@Data
@AutoMapper(target = TreeNode.class, cycleAvoiding = true)
public class TreeNodeDto {
    private TreeNodeDto parent;
    private List<TreeNodeDto> children;
}

編譯生成的轉換邏輯如下:

public TreeNodeDto convert(TreeNode arg0, CycleAvoidingMappingContext arg1) {
    TreeNodeDto target = arg1.getMappedInstance(arg0, TreeNodeDto.class);
    if (target != null) {
        return target;
    }

    if (arg0 == null) {
        return null;
    }

    TreeNodeDto treeNodeDto = new TreeNodeDto();

    arg1.storeMappedInstance(arg0, treeNodeDto);

    treeNodeDto.setParent(demoConvertMapperAdapterForCycleAvoiding.iglm_TreeNodeToTreeNodeDto(arg0.getParent(), arg1));
    treeNodeDto.setChildren(
        demoConvertMapperAdapterForCycleAvoiding.iglm_TreeNodeToTreeNodeDto(arg0.getChildren(), arg1));

    return treeNodeDto;
}
  • AutoMappingReverseAutoMapping 支援 qualifiedByNameconditionQualifiedByNamedependsOn 屬性
  • AutoMappings 支援配置在方法上面

相關文章