MainTest.java
/** * 模拟通过MapStruct把user对象转换成UserRoleDto对象 */ @Test public void test2() { UserRoleDto userRoleDto = UserRoleMapper.INSTANCES.toUserRoleDto(user); System.out.println(userRoleDto); }呃,很明显,运行竟然报错了,具体异常如下:
核心是这一句 :java.lang.ClassNotFoundException: Cannot find implementation for top.zhoudl.mapstruct.UserRoleMapper ,也就是说没有找到 UserRoleMapper 类的实现类。
通过查阅一些资料可得:
MapStruct 是一个可以处理注解的Java编译器插件,可以在命令行中使用,也可以在 IDE 中使用。MapStruc t有一些默认配置,但是也为用户提供了自己进行配置的途径。缺点就是这玩意在使用工具自带的编译器时不会生成实现类,需要通过 maven 的方式来进行编译,然后才会生成实现类。
所以我们需要增加一个编译插件到 pom 文件中:
<!-- 引入 processor --> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.3.0.Final</version> <scope>provided</scope> </dependency> <!--为 Maven compile plugin 设置 annotation processor --> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.2.0.Final</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins>然后我们运行程序就可以得到自己想要的结果了
安装 MapStruct 插件使用 MapStruct,还有一个缺点就是,当属性改名的时候,因为在 Mapper 上注解中配置的名字是在字符串里面,因此不会自动同步的。所以 MapStruct 提供了一个插件来解决这个问题,同时还提供代码自动提示、点击跳转到实现等功能。
关于插件的更多信息,参见 MapStruct support for IntelliJ IDEA
安装插件的过程在 IDEA 中依次打开 File - > Settings - > Plugins
然后在 Markeyplace 搜索框中输入 mapstruct,点击 install,然后重启 IDE 即可。
一些可能会出现的问题找不到注释处理程序:在 pom.xml 中增加 mapstruct-processor 的依赖
没有找到实现类:在 pom.xml 中加入对 mapstruct-processor 的依赖
在 IDEA 里面 enable Annotation Processor
使用 Lombok 的情况下,编译时报 Data 类的 setter/getter 找不到:把 lombok 加入到annotationProcessorPath,如下图
总结MapSturct 是一个生成类型安全, 高性能且无依赖的 JavaBean 映射代码的注解处理器(annotation processor)。
作为一个注解处理器, 通过MapStruct 生成的代码具有怎么样的优势呢?抓一下重点:
注解处理器
可以生成 JavaBean 之间的映射代码
类型安全, 高性能, 无依赖性
高性能这是相对反射来说的, 反射需要去读取字节码的内容, 花销会比较大。 而通过 MapStruct 来生成的代码, 其类似于人手写,代码执行速度上可以得到保证。(前面例子中生成的代码可以在编译后看到,在项目的 target/generated-sources/annotations 目录里可以看到具体代码)。
易于 debug在我们生成的代码中, 我们可以轻易的进行 debug。但是如果是使用反射实现代码的时候, 一旦出现了问题, 很多时候是比较难找到原因。
使用相对简单如果是完全映射的, 使用起来肯定没有反射简单。 用类似 BeanUtils 这些工具一条语句就搞定了。 但是,如果需要进行特殊的匹配(特殊类型转换, 多对一转换等), MapStruct 的优势就比较明显了,基本上我们只需要在使用的时候声明一个接口, 接口下写对应的方法, 就可以使用了(当然, 如果有特殊情况, 是需要额处理一下的)。
代码独立生成的代码是对立的, 没有运行时的依赖
本文首发于微信公众号 【程序猿杂货铺】,关注公众号,获取更多精彩文章!