关于Java属性映射正确姿势的探讨

来源:10-9 出现缓存雪崩该怎么办?如何避免?

LBruce

2021-06-23

背景

日常开发中为了更容易维护,易于拓展等原因会使用各种分层领域模型(BO,VO,DTO,DO…),这就会存在一个非常棘手的问题即:编写不同的模型之间相互转换的代码非常麻烦…

常见的 Java 属性映射方式有以下几种:

Getter/Setter 方式
org.apache.commons.beanutils.BeanUtils
org.springframework.beans.BeanUtils
org.dozer.Mapper
mapstruct

不同方式之间的比较:

除了自己写get/set方法外,其余的方式都可以归属于利用属性转换工具做转换。

属性转换工具的优势:

用起来方便,往往一行行代码就实现多属性的转换,而且属性不对应可以通过注解或者修改配置方式自动适配,功能非常强大。

属性转换工具的缺点:

  1. 对象映射的时候,如果属性不完全一致则容易出错
  2. 有些转换工具,可能会出现意想不到的 BUG
  3. 基于反射的映射工具实现映射,性能会稍差一点,比不上get/set
  4. mapstruct是用操作字节码的方式,编译时会自动生成转换工具的实现类实现转换,性能理论上比反射快,但是一样存在第5点的问题。
  5. 基于反射和字节码增强技术的映射工具实现的映射,对一个类属性的修改不容易感知到对其它转换类的影响。这一点尤其致命!

一个 UserDO 如果属性超多,转换到 UserDTO 再被转换成 UserVO 。如果你修改 UserDTO 的一个属性命名,其它类待映射的类新增的对应属性有一个字母写错了,编译期间不容易发现问题,造成 BUG。
如果使用原始的 Getter/Setter 方式转换,修改了 UserDO 的属性,那么转换代码就会报错,编译都不通过,在编译阶段就能提醒我们修改属性所带来的错误影响。

手写get/set的优势:

性能优于反射,并且更重要的是对一个类属性的修改非常容易感知得到,如果转换代码没跟上所做变动,那么在编译期间就会报错,避免Bug产生。

手写get/set缺点:

繁琐,不过可以借助一些IDEA插件,比如GenerateAllSetter 或者 GenerateO2O,稍微减少一些工作量。

我的属性映射姿势

为了避免转换函数散落到多个业务类中,在项目中单独新建一个convert包,在convert包下实现一个个convert工具类,负责实现层与层之间对象的转换,然后安装上IDEA插件GenerateAllSetter,更快地完成get/set~

一哥对此有什么见解?谢谢一哥解答。

写回答

1回答

张勤一

2021-06-26

同学你好:

    首先感谢你的分享,我这里提出两点建议:

    (1)这类代码确实是非常麻烦而且都是重复性的,没有任何技术含量的;所以,我建议越简单的实现越好(get、set 就挺好,而且一定不会出错)

    (2)我们更多的应该把精力放在业务逻辑上,这些对象之间的转换,方法实现太多,任意挑选一种你习惯的和喜欢的就可以了,不需要考虑太多 『漂亮』的实现,对你的技术提升其实没有太多的帮助!


    我是勤一,欢迎随时找我!

2
0

Java实操避坑指南 SpringBoot/MySQL/Redis错误详解

掌握业务开发中各种类型的坑,,Java web开发领域通用

466 学习 · 204 问题

查看课程