V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
alva0
V2EX  ›  分享创造

MapStructPlus 1.4.0 发布,更加轻量,速度更快

  •  
  •   alva0 · 251 天前 · 977 次点击
    这是一个创建于 251 天前的主题,其中的信息可能已经有所发展或是发生改变。

    MapStruct Plus 是 MapStruct 的增强工具,在 Mapstruct 的基础上,实现了自动生成 Mapper 接口的功能,并强化了部分功能,使 Java 类型转换更加便捷、优雅。


    此次迎来了一次较大版本的更新,更新日志如下:

    • 优化复杂对象转换逻辑,占用元空间更小!性能更快!

    此版本针对于复杂对象的自动转换逻辑,进行了优化和部分的重新设计,减少了一些不必要的转换方法,占用元空间更小。

    RuoYi-Vue-Plus 为例,使用新版本后,元空间占用减少了 7MB ,根据项目的复杂程度不同,减少的内存占用也有所不同。

    且根据 issue#67 中提到,在 SpringBoot + Aop 场景下,性能会受影响, 在新版本中,修改了实现方式,性能比提升一半以上。

    • 去除 hutool 等依赖,目前项目中只依赖了 MapStruct

    上次分享该项目,也有人提出内置了 hutool 太重,从 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 支持配置在方法上面
    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2795 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 06:17 · PVG 14:17 · LAX 22:17 · JFK 01:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.