背景
在将项目升级到 Spring Boot 3.2.x + Java 17 后,项目在启动阶段直接退出,没有Exception in thread "main" 或 Caused by,导致问题难以定位。
最初怀疑过:
- Knife4j / Swagger
- Hutool 工具类
- 枚举定义
- 配置文件错误
但检查后发现都不是原因。
报错信息
开启 DEBUG 日志后,启动过程中出现如下关键信息:
1 | Creating MapperFactoryBean with name 'userMapper' |
随后 Spring 容器初始化被中断,程序直接退出。
这个异常没有堆栈向下追踪信息。
排查过程
1. 确认异常类型
程序属于:
- 启动阶段直接退出(exit)
- 而不是卡死或运行时报错
说明问题发生在 Spring 容器初始化早期阶段。
2. 锁定异常位置
从日志可以确认异常发生在:
1 | MapperFactoryBean 创建阶段 |
并且与 MyBatis Mapper 扫描 直接相关。
3. 检查依赖树
执行命令:
1 | mvn dependency:tree | findstr mybatis |
输出如下:
1 | com.baomidou:mybatis-plus-boot-starter:3.5.9 |
这里发现了一个关键问题:
mybatis-spring 2.1.2 是为 Spring 5 设计的
而 Spring Boot 3 使用的是 Spring Framework 6
4. 问题本质
Spring Framework 6 对 FactoryBean 的类型推断规则进行了严格校验:
- 不再接受
String类型的factoryBeanObjectType - 必须是
Class<?>
而 mybatis-spring 2.x 内部仍使用旧方式注册 Bean 元数据,导致 Spring 6 直接抛出:
1 | Invalid value type for attribute 'factoryBeanObjectType' |
由于这是 容器元数据校验失败,并非运行期异常,因此不会有常见的 Caused by 堆栈。
解决方案
1. 排除不兼容的 mybatis-spring
在 mybatis-plus-boot-starter 中排除旧依赖:
1 | <dependency> |
2. 手动引入 Spring 6 兼容版本
1 | <dependency> |
3. 清理并重新构建
1 | mvn clean |
然后在 IDEA 中重新刷新 Maven 依赖。
4. 验证修复结果
再次执行:
1 | mvn dependency:tree | findstr mybatis-spring |
确认只存在:
1 | org.mybatis:mybatis-spring:3.0.3 |
项目即可正常启动。
总结
这次问题的几个特点:
- 无
Caused by - 无
main线程异常 - 代码本身正确
- 只在 Spring Boot 3 + MyBatis 组合下触发
- 依赖版本与 Spring 6 不兼容
(注)虽然感觉可能性不大,但旧的依赖可能是MyBatis-Plus自己引入的。但因为无法百分百确定自己当初有没有引入,所以不能实锤。