MapStruct 的 @Mapping 注解仅声明映射元数据,真正生成代码的是编译期注解处理器;该处理器扫描 @Mapper 接口,依据 @Mapping 配置生成类型安全的实现类,如 UserMapperImpl,并支持字段自动匹配、表达式调用及 Spring 集成。

MapStruct 的 @Mapping 注解本身不直接生成代码,它只是声明式配置;真正生成映射代码的是 MapStruct 提供的编译期注解处理器(Annotation Processor),在 javac 编译阶段自动运行,扫描带有 @Mapper 的接口并根据 @Mapping 等注解生成具体的实现类。
注解处理器如何被触发
MapStruct 依赖标准的 Java 注解处理机制。只要项目中正确引入了 MapStruct 的 processor 依赖(如 mapstruct-processor),并在构建工具中启用注解处理,javac 就会在编译时自动发现并调用 MapStruct 的 MapperProcessor。
- Maven 中需确保
mapstruct-processor在compile范围(或通过annotationProcessorPaths显式配置) - IDE(如 IntelliJ 或 Eclipse)需开启“Enable annotation processing”,否则可能看不到生成的代码或报错
- 生成的实现类默认放在
target/generated-sources/annotations(Maven)或类似路径下,属于编译源码的一部分
@Mapping 是如何参与代码生成的
@Mapping 本身不带逻辑,只提供元数据:比如指定源字段名、目标字段名、转换方式、默认值或忽略规则。注解处理器读取这些信息后,结合 @Mapper 接口定义的映射方法签名,拼装出类型安全的 Java 赋值和转换逻辑。
- 例如
@Mapping(source = "userName", target = "name")→ 生成target.setName(source.getUserName()); -
@Mapping(target = "status", expression = "java(com.example.StatusMapper.toStatus(source.getState()))")→ 插入对应表达式调用 - 未显式配置的字段,处理器按名称自动匹配(驼峰转换),也可通过
@BeanMapping控制策略
为什么必须用 interface + @Mapper
MapStruct 要求映射逻辑定义在 interface 上,并标注 @Mapper,因为注解处理器只扫描满足条件的接口:它是基于接口契约生成实现类(而非修改原有类)。生成的类是普通 Java 类,实现了该接口,且可被 Spring 等框架直接注入(配合 @Mapper(componentModel = "spring"))。
立即学习“Java免费学习笔记(深入)”;
- 不能对
class使用@Mapper—— 这不是 MapStruct 的设计模型 - 生成类名默认为接口名 + “Impl”,如
UserMapper→UserMapperImpl - 所有
@Mapping必须位于被@Mapper标记的接口内,否则会被忽略
常见编译失败原因和检查点
如果没看到生成代码或编译报错,通常不是 @Mapping 写错了,而是注解处理环节未就绪:
- 依赖缺失:只有
mapstruct运行时依赖,没加mapstruct-processor编译依赖 - Lombok 干扰:若实体类用了
@Data等 Lombok 注解,需确保 Lombok 的 processor 在 MapStruct 之前执行(Maven 中顺序重要,IDE 中需启用 Lombok 支持) - 字段类型不匹配且无隐式转换:如 source 是
String,target 是LocalDate,又没配@Mapper#uses或@Named转换器,处理器会报错而非静默跳过


















