如何让MapStruct使用Lombok Builder解决私有构造调用报错问题
问题根因
这类编译错误的核心是注解处理器执行顺序错乱、跨处理器的元数据传递链路缺失,导致MapStruct在Lombok完成类结构生成前就提前扫描了目标类:
- 扫描阶段MapStruct看到的是还未被Lombok处理的空类结构,默认判定类存在公共无参构造,因此生成
new SomeDto()的调用代码 - 后续Lombok处理器运行后,为@Value注解的类生成了私有全参构造、@Builder注解的建造者方法,此时MapStruct之前生成的代码就会因为访问私有构造触发编译报错
正确配置调整步骤
1. 校准注解处理器加载顺序
在maven-compiler-plugin的annotationProcessorPaths节点下,必须严格按照固定顺序声明三个处理器,禁止调换顺序:
- 第一位放置Lombok处理器,优先完成所有Lombok注解的类结构转换
- 第二位放置lombok-mapstruct-binding适配组件,打通Lombok和MapStruct之间的元数据传递通道
- 第三位放置MapStruct处理器,在拿到Lombok处理后的完整类结构后生成映射代码
调整后的配置片段示例:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${compiler-plugin.version}</version> <configuration> <annotationProcessorPaths> <!-- 以下顺序绝对不能调换 --> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.16</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok-mapstruct-binding</artifactId> <version>0.2.0</version> </path> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.4.1.Final</version> </path> </annotationProcessorPaths> </configuration> </plugin>
2. 版本兼容性校验
所有依赖的版本需要匹配对应能力要求,否则会出现识别失效:
- Lombok 版本不低于1.18.16:该版本开始暴露Lombok生成的Builder方法元数据供MapStruct识别
- lombok-mapstruct-binding 版本固定匹配0.2.0:和MapStruct 1.4.x全系列版本兼容,缺失该组件会导致MapStruct完全感知不到Lombok生成的类结构
- mapstruct-processor 版本不低于1.4.0.Final:1.4.0之前的版本不支持自动识别Builder模式映射,遇到仅有私有构造的不可变类会直接生成错误代码
3. 生成结果验证
配置生效后,MapStruct生成的实现类不会再出现直接调用私有构造的代码,会自动适配Builder链路生成映射逻辑,同时也不会出现之前错误代码里空判断对象写错的问题,示例代码如下:
@Generated( value = "org.mapstruct.ap.MappingProcessor", comments = "version: 1.4.1.Final, compiler: javac" ) public class SomeMapperImpl implements SomeMapper { @Override public SomeDto map(SomeModel someModel) { if (someModel == null) { return null; } // 自动使用Builder生成实例 SomeDto.SomeDtoBuilder someDtoBuilder = SomeDto.builder(); // 逐字段完成属性拷贝 return someDtoBuilder.build(); } @Override public SomeModel map(SomeDto someDto) { if (someDto == null) { return null; } SomeModel.SomeModelBuilder someModelBuilder = SomeModel.builder(); return someModelBuilder.build(); } }
常见踩坑提醒
- 不要在项目普通依赖节点额外引入
mapstruct-processor包,否则会导致注解处理器被重复加载,执行顺序被打乱,哪怕配置顺序正确也可能失效 - 不要省略
lombok-mapstruct-binding组件配置:很多旧版教程只配置Lombok和MapStruct处理器,没有这个适配层,MapStruct会完全看不到Lombok生成的构造、Builder方法,依然会生成调用无参构造的错误代码 - IDEA环境下需要单独开启「Enable annotation processing」开关,否则IDE内置的增量编译会绕过maven配置的处理器链路,出现本地IDE编译报错但命令行编译正常的情况
内容的提问来源于stack exchange,提问作者Robert van der Spek
相关产品推荐
相关产品推荐

