这个原因主要是因为 Lombok 也需要编译期间自动生成代码,这就可能导致两者冲突,当 MapStruct 生成代码时,还不存在 Lombok 生成的代码。
解决办法可以在 maven-compiler-plugin
插件配置中加入 Lombok,如下:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <!-- depending on your project --> <target>1.8</target> <!-- depending on your project --> <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.3.1.Final</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </path> <!-- other annotation processors --> </annotationProcessorPaths> </configuration> </plugin>
输出 DO 与 DTO 如下:
从上图中我们可以得到一些结论:
- 部分类型不一致,可以自动转换,比如
- 基本类型与包装类型
- 基本类型的包装类型与 String
- 深拷贝
上面介绍的例子介绍一些简单字段映射,如果小伙伴在工作总共还碰到其他的场景,可以先查看一下这个工程,查看一下有没有结局解决办法:https://github.com/mapstruct/mapstruct-examples
上面我们已经知道 MapStruct 在编译期间就生成了代码,下面我们来看下自动生成代码:
public class StudentMapperImpl implements StudentMapper { public StudentMapperImpl() { } public StudentDO dtoToDo(StudentDTO studentDTO) { if (studentDTO == null) { return null; } else { StudentDO studentDO = new StudentDO(); studentDO.setNumber(studentDTO.getNo()); try { if (studentDTO.getCreateDate() != null) { studentDO.setCreateDate((new SimpleDateFormat("yyyy-MM-dd")).parse(studentDTO.getCreateDate())); } } catch (ParseException var4) { throw new RuntimeException(var4); } studentDO.setName(studentDTO.getName()); if (studentDTO.getAge() != null) { studentDO.setAge(String.valueOf(studentDTO.getAge())); } List<String> list = studentDTO.getSubjects(); if (list != null) { studentDO.setSubjects(new ArrayList(list)); } studentDO.setCourse(studentDTO.getCourse()); return studentDO; } } }
从生成的代码来看,里面并没有什么黑魔法,MapStruct 自动生成了一个实现类 StudentMapperImpl
,里面实现了 dtoToDo
,方法里面调用 getter/setter
设值。
从这个可以看出,MapStruct 作用就相当于帮我们手写getter/setter
设值,所以它的性能会很好。
总结
看文这篇文章,我们一共学习了 7 个属性复制工具类,这么多工具类我们该如何选择那?阿粉讲讲自己的一些见解:
第一,首先我们直接抛弃 Apache Beanutils ,这个不用说了,阿里巴巴规范都这样定了,我们就不要使用好了。
第二,当然是看工具类的性能,这些工具类的性能,网上文章介绍的比较多,阿粉就复制过来,大家可以比较一下。
来自:https://www.hollischuang.com/archives/5337
可以看到 MapStruct 的性能可以说还是相当优秀。那么如果你的业务对于性能,响应等要求比较高,或者你的业务存在大数据量导入/导出的场景,而这个代码存在对象转化,那就切勿使用 Apache Beanutils, Dozer 这两个工具类。
第三,其实很大一部分应用是没有很高的性能的要求,只要工具类能提供足够的便利,就可以接受。如果你的业务中没有很复杂的的需求,那么直接使用 Spring Beanutils 就好了,毕竟 Spring 的包大部分应用都在使用,我们都无需导入其他包了。
那么如果业务存在不同类型,不同的字段名,那么可以考虑使用 orika 等这种重量级工具类。
好了,今天的文章就到这里为止了~