mapstruct需同时引入mapstruct和mapstruct-processor依赖,版本一致且lombok依赖须声明在processor之前;maven需配置annotationprocessorpaths,spring boot项目推荐componentmodel="spring"。

MapStruct 依赖怎么加才不会编译失败
MapStruct 不是运行时库,而是编译期代码生成器,所以 mapstruct 和 mapstruct-processor 必须配对使用,缺一不可。
- 只加
mapstruct(不加 processor):编译通过但无 mapper 实现类生成,运行时报NullPointerException或找不到 bean - 只加
mapstruct-processor(没声明mapstruct):IDE 可能报红,@Mapper注解无法解析,Maven 编译直接失败 - Maven 中推荐统一用
mapstruct的 BOM 管理版本,避免 processor 版本错配;Gradle 用户注意annotationProcessor需显式启用,不能只靠compileOnly
示例(Maven):
<dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.5.5.Final</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.5.5.Final</version> <scope>provided</scope> </dependency>
为什么 Lombok + MapStruct 一起用会报错
Lombok 在编译期插入 getter/setter,而 MapStruct 处理的是原始源码结构;如果顺序不对,MapStruct 看不到 Lombok 生成的字段或方法,就会生成空实现或编译失败。
- 必须确保 Lombok 的注解处理器先于 MapStruct 执行;Maven 默认按声明顺序执行,所以
lombok依赖要写在mapstruct-processor前面 - IntelliJ 用户需开启
Enable annotation processing,并确认Lombok plugin已安装且启用;否则 IDE 内部编译和 Maven 编译行为不一致 - 常见错误现象:
Cannot resolve symbol 'xxx' in mapping method,实际是 Lombok 没生效导致字段不可见
Maven 编译插件不配置 mapstruct source directory 会怎样
MapStruct 默认只扫描 src/main/java 下的 @Mapper 接口,但如果 mapper 接口放在测试目录、或用了多模块结构中的独立 mapper 模块,不显式配置 source 目录会导致生成失败且无提示。
立即学习“Java免费学习笔记(深入)”;
- Spring Boot 多模块项目中,若 mapper 定义在
common模块,但该模块未引入mapstruct-processor,则即使有@Mapper也不会生成实现类 - Maven 的
maven-compiler-plugin需明确指定annotationProcessorPaths,尤其在 JDK 17+ 上,否则 processor 可能被跳过 - 错误表现:编译成功,但 Spring 启动时报
No qualifying bean of type 'XxxMapper',且 target/classes 下找不到对应 MapperImpl 类
关键配置片段:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
@Mapper 的 componentModel 参数选哪个
这个参数决定生成的 MapperImpl 类是否带 Spring 组件注解,直接影响能否被自动注入;选错会导致 @Autowired 失败或循环依赖警告。
-
componentModel = "default":生成普通类,无任何注解,需手动 new 或用@Bean注册 -
componentModel = "spring":生成类上加@Component,可直接@Autowired;但要求项目已启用 Spring 组件扫描,且不能和 Lombok 的@RequiredArgsConstructor冲突(后者可能生成多个构造函数) -
componentModel = "jsr330":用@Named,适合 CDI 环境,Java SE 项目慎用 - Spring Boot 项目默认选
"spring",但要注意:若 mapper 接口有泛型或复杂继承关系,"spring"模式下可能触发 Spring 的代理逻辑,导致getClass()返回 CGLIB 类而非原始类
示例:
@Mapper(componentModel = "spring")
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); // 这行在 componentModel="spring" 时通常不用
}
MapStruct 的核心陷阱不在语法,而在编译链路的“看不见”环节:注解处理器顺序、source 目录可见性、以及 Spring 上下文对生成类的加载时机。这些地方一漏,就只能看到运行时报错,却查不到生成失败的日志。










