Gradle与Maven中Mapstruct识别非JavaBean方法差异原因排查
问题:Gradle与Maven中Mapstruct处理非JavaBean方法的差异
代码场景
抽象基类与实现类代码如下:
@MappedSuperclass @EntityListeners(CRUDListener.class) public abstract class AbstractAR<A extends AbstractAR<A, ID>, ID> extends AbstractAggregateRoot<A> implements DomainEntity<A, ID> { public void validate() { } protected boolean enableSelectEvent() { return false; } @SuppressWarnings("unchecked") public A update(Consumer<A> updater) { A a = (A) this; updater.accept(a); return a; } } @Getter @Setter @ToString(callSuper = true) @NoArgsConstructor @Entity @Table(name = SimpleDO.TABLE_NAME) public class SimpleDO extends AbstractAR<SimpleDO, String> { public static final String TABLE_NAME = "simple_table"; @Id private String id; @Column(name = "name", nullable = false) @Comment("name") private String name; }
问题现象
使用Mapstruct 1.4.2.Final或1.5.5.Final时:
- Gradle项目编译报错:
Unmapped target property: "update",必须显式添加@Mapping(target = "update", ignore = true)才能通过编译 - 相同版本Mapstruct、相同代码在Maven项目中可正常编译运行
构建配置
Gradle配置
dependencies { implementation 'org.mapstruct:mapstruct' implementation 'org.mapstruct:mapstruct-jdk8' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' annotationProcessor 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok-mapstruct-binding' annotationProcessor 'org.mapstruct:mapstruct' annotationProcessor 'org.mapstruct:mapstruct-processor' annotationProcessor 'org.mapstruct:mapstruct-jdk8' testAnnotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' testAnnotationProcessor 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok-mapstruct-binding' testAnnotationProcessor 'org.mapstruct:mapstruct' testAnnotationProcessor 'org.mapstruct:mapstruct-processor' testAnnotationProcessor 'org.mapstruct:mapstruct-jdk8' }
Maven配置
<!-- My maven pom.xml --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven.compiler.version}</version> <configuration> <annotationProcessorPaths> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</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>${mapstruct.version}</version> </path> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-jdk8</artifactId> <version>${mapstruct.version}</version> </path> <path> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <version>${spring-boot.version}</version> </path> </annotationProcessorPaths> </configuration> </plugin>
原因分析
1. 注解处理器执行顺序差异
- Maven的
annotationProcessorPaths严格遵循配置顺序执行注解处理器:Lombok先处理类(生成getter/setter等),接着lombok-mapstruct-binding向Mapstruct传递处理后的类元数据,最后Mapstruct基于处理后的类生成映射代码,能正确识别update是自定义方法而非JavaBean属性。 - Gradle默认不保证
annotationProcessor依赖的执行顺序,即使声明顺序是Lombok在前,Gradle可能因依赖解析逻辑调整顺序,导致Mapstruct先于Lombok处理类。此时Mapstruct读取的是原始未修改的类,会把update方法误判为需要映射的目标属性,从而抛出未映射属性的错误。
2. 冗余依赖导致类路径混乱
Gradle配置中,将org.mapstruct:mapstruct(API包)和mapstruct-jdk8添加到了annotationProcessor依赖中,这是不必要的。Mapstruct的API包只需放在implementation依赖,annotationProcessor中仅需保留mapstruct-processor。冗余的API包可能干扰Mapstruct处理器的类扫描逻辑。
解决方法
调整Gradle依赖配置
移除annotationProcessor和testAnnotationProcessor中的冗余Mapstruct依赖,仅保留必要处理器:
dependencies { implementation 'org.mapstruct:mapstruct' implementation 'org.mapstruct:mapstruct-jdk8' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' annotationProcessor 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok-mapstruct-binding' annotationProcessor 'org.mapstruct:mapstruct-processor' testAnnotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' testAnnotationProcessor 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok-mapstruct-binding' testAnnotationProcessor 'org.mapstruct:mapstruct-processor' }
强制指定处理器执行顺序
在Gradle脚本中添加配置,确保Lombok处理器先于Mapstruct执行:
tasks.withType(JavaCompile) { options.annotationProcessorPath = files( // 先加载Lombok相关处理器 configurations.annotationProcessor.filter { it.name.contains('lombok') }, configurations.annotationProcessor.filter { it.name.contains('lombok-mapstruct-binding') }, // 再加载Mapstruct处理器 configurations.annotationProcessor.filter { it.name.contains('mapstruct-processor') }, // 最后加载其他处理器 configurations.annotationProcessor.filter { it.name.contains('spring-boot-configuration-processor') } ) }
内容的提问来源于stack exchange,提问作者honhim
相关产品推荐
相关产品推荐

