You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Boot 3.5.4整合MapStruct时出现AccountMapper的ClassNotFoundException问题求助

Spring Boot 3.5.4整合MapStruct时出现AccountMapper的ClassNotFoundException问题求助

我最近在把MapStruct和Spring Boot 3.5.4整合时遇到了一个棘手的问题——应用启动时总是抛出ClassNotFoundException: AccountMapper。明明MapStruct注解处理器已经正确生成了带@Component注解的实现类AccountMapperImpl,但Spring就是找不到AccountMapper接口对应的Bean。我已经给Mapper接口加了@Mapper(componentModel = "spring"),甚至试过用MappingConstants.ComponentModel.SPRING常量,但问题依旧。错误出现在Spring组件扫描阶段,具体是处理引用该Mapper的配置类时,提示AccountService中的accountMapper字段找不到对应Bean。源码里的接口存在且编译成功,但运行时Spring上下文就是识别不到它。有没有大佬能帮忙分析下,为啥注解处理器生成的类没被正确加入Spring Boot的类路径或上下文?

环境信息

  • Spring Boot: 3.5.4
  • MapStruct: 1.5.5.Final
  • Java: 21
  • Maven: 3.x
  • 编辑器: VS Code

错误详情

Caused by: java.lang.ClassNotFoundException: AccountMapper
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:528)

Description: Field accountMapper in com.demo.demo.service.AccountService required a bean of type 'com.demo.demo.mapper.AccountMapper' that could not be found.

Action: Consider defining a bean of type 'com.demo.demo.mapper.AccountMapper' in your configuration.

2025-08-16T13:57:58.031-05:00 WARN 60525 --- [finance-core-service] [ main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener] to prepare test instance [com.demo.demo.FinanceCoreServiceApplicationTests@7f72855d]

相关代码

AccountMapper接口

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingConstants;
import com.demo.finance_core_service.dto.AccountBaseDTO;
import com.demo.finance_core_service.model.Account;

// 也试过用这个:@Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
@Mapper(componentModel = "spring")
public interface AccountMapper {
    @Mapping(target = "accountId", ignore = true)
    @Mapping(target = "transactions", ignore = true)
    Account toEntity(AccountBaseDTO dto);
    AccountBaseDTO toDto(Account entity);
}

生成的AccountMapperImpl实现类

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2025-08-16T13:52:56-0500",
    comments = "version: 1.5.5.Final, compiler: javac, environment: Java 23.0.1"
)
@Component
public class AccountMapperImpl implements AccountMapper {
    // 具体实现代码...
}

AccountService类

@Service
public class AccountService {
    @Autowired
    private AccountRepository accountRepository;
    @Autowired
    private AccountMapper accountMapper; // 找不到这个Bean

    @Transactional
    public Account createAccount(AccountBaseDTO newAccount) {
        Account account = accountMapper.toEntity(newAccount);
        return accountRepository.save(account);
    }
}

pom.xml完整关键配置(补充你未贴全的部分)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.4</version>
        <relativePath/>
    </parent>
    <groupId>com.demo</groupId>
    <artifactId>finance-core-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>demo</description>
    <properties>
        <java.version>21</java.version>
        <mapstruct.version>1.5.5.Final</mapstruct.version>
        <lombok.version>1.18.38</lombok.version>
    </properties>
    <dependencies>
        <!-- Spring Boot Starters -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <!-- MapStruct核心依赖 -->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${mapstruct.version}</version>
        </dependency>
        <!-- Lombok依赖 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
            <!-- 注解处理器配置 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <annotationProcessorPaths>
                        <!-- MapStruct注解处理器 -->
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${mapstruct.version}</version>
                        </path>
                        <!-- Lombok注解处理器 -->
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </path>
                        <!-- Lombok与MapStruct绑定处理器(可选但建议) -->
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok-mapstruct-binding</artifactId>
                            <version>0.2.0</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

排查方向与解决方案

根据你的情况,整理了几个常见的解决思路,你可以逐一尝试:

  1. 确认Maven注解处理器配置完整
    从你最初贴的pom片段来看,缺少了关键的注解处理器配置。MapStruct必须在maven-compiler-pluginannotationProcessorPaths中声明mapstruct-processor,且版本要和核心依赖一致。如果同时用Lombok,还要注意处理器的顺序,建议按上面pom的配置来。

  2. 检查生成类的路径与包结构
    执行mvn clean compile后,去target/generated-sources/annotations目录下查看,确认AccountMapperImpl的包路径和AccountMapper接口完全一致。如果路径不匹配,Spring扫描不到实现类,就会找不到Bean。

  3. 验证Spring组件扫描范围
    @SpringBootApplication默认扫描启动类所在包及其子包,如果AccountMapper所在包不在这个范围内,Spring就识别不到它。可以在启动类上添加@ComponentScan(basePackages = {"com.demo.demo.mapper", "com.demo.demo.service"})明确指定扫描范围。

  4. 清理IDE编译缓存
    VS Code偶尔会出现编译缓存异常,你可以试试:

    • 执行mvn clean install清空本地编译产物后重新编译
    • 删除项目根目录的.vscodetarget文件夹,重启VS Code后重新导入项目
    • 检查Java插件是否开启自动编译,手动触发一次完整编译
  5. 升级MapStruct版本
    MapStruct 1.5.5.Final是较旧的版本,Spring Boot 3.x基于Jakarta EE规范,旧版MapStruct对Jakarta的支持可能不完善。建议升级到最新稳定版(如1.6.2+),看看是否能解决兼容性问题。

  6. 改用构造注入替代字段注入
    字段注入可能因Bean初始化顺序问题导致找不到依赖,试试构造注入:

    @Service
    public class AccountService {
        private final AccountRepository accountRepository;
        private final AccountMapper accountMapper;
    
        // 这里@Autowired在Spring 4.3+可以省略
        public AccountService(AccountRepository accountRepository, AccountMapper accountMapper) {
            this.accountRepository = accountRepository;
            this.accountMapper = accountMapper;
        }
        // 业务方法...
    }
    

希望这些方法能帮你解决问题,如果还有其他细节可以补充,我再帮你进一步分析!

内容来源于stack exchange

火山引擎 最新活动