从启动失败、循环依赖到事务失效与 CORS 跨域,覆盖 Spring Boot 开发中最常踩到的坑,每条都附根因分析与验证解法。
启动失败、自动配置、Servlet 容器、Profile、打包
应用被当成 Web 应用却找不到容器工厂,启动即报 missing ServletWebServerFactory bean。
访问接口见到白页,提示 no explicit mapping for /error。多是请求没匹配到 Controller,包结构或注解写错。
Spring Boot 2.6 默认改用 PathPatternParser,springfox 不兼容,启动即抛 nested NPE。
升级到 Spring Boot 3 最低要 Java 17,javax.* 全部换成 jakarta.*,Spring Security 配置也需重写。
内嵌 Web 服务器默认绑 8080,一旦被其他进程占用就启动失败。先定位占用进程,再改端口或释放。
Bean 缺失/冲突、循环依赖、@ComponentScan
访问接口见到白页,提示 no explicit mapping for /error。多是请求没匹配到 Controller,包结构或注解写错。
注入时报 NoSuchBeanDefinitionException,多是类不在 @ComponentScan 范围内,跨包 Bean 漏掉。
Spring Boot 2.6 起默认禁止 Bean 循环依赖,升级后启动失败,可重构或开 allow-circular-references。
DataSource、JPA、连接池、Flyway、MyBatis
Flyway 启动校验失败,报 Migration checksum mismatch,已执行过的迁移脚本被改过,本地与库里 checksum 对不上。
引入 spring-boot-starter-data-jpa 却没配连接,自动配置强制装配 DataSource 又找不到 url。
运行时冒 HikariPool Connection is not available,多数是连接借出后没归还,直到超时。
查 N 个父实体再遍历访问关联会触发 N 条额外查询,用 JOIN FETCH、@EntityGraph 或 @BatchSize 优化。
@Transactional 失效、传播、缓存
@Transactional 标在 private 方法上既不报错也不生效,代理只能拦截穿过代理的外部调用,private 方法无法被覆盖。
Spring Boot 默认用 CGLIB 代理,final 类或方法无法被子类化,注解静默失效或抛 AopConfigException。
@Transactional 默认只回滚 RuntimeException 和 Error,抛受检异常时事务照常提交,需配 rollbackFor。
NESTED 依赖数据库保存点实现部分回滚,JPA 方言不支持 savepoint 时直接抛 TransactionSystemException。
事务上下文用 ThreadLocal 绑定当前线程,new Thread 或 @Async 里的写操作拿不到事务,独立提交且不跟随外层回滚。
容器里找不到名为 transactionManager 的 Bean 时,@Transactional 方法调用直接抛异常,多因自动装配失效。
配多数据源后 @Transactional 按类型找事务管理器,多个候选就抛 NoUniqueBeanDefinitionException。
REQUIRES_NEW 挂起外层事务并开启独立新事务,内层一旦提交,外层回滚无法撤销,产生脏数据。
Spring 只在异常穿过代理边界时才回滚,事务方法内 try-catch 捕获异常未重新抛出,代理感知不到,事务照常提交。
内层事务异常被外层 catch 吞掉后继续提交,但物理事务已标记 rollback-only,提交时抛 UnexpectedRollbackException。
同类里用 this 调用带 @Async 或 @Transactional 的方法,注解会静默失效,可抽 Bean、注入自身代理或走 AopContext。
Controller、参数校验、Jackson、CORS、异常处理
RestTemplate/WebClient、超时、连接
@Async、定时任务、消息队列
容器里找不到名为 transactionManager 的 Bean 时,@Transactional 方法调用直接抛异常,多因自动装配失效。
配多数据源后 @Transactional 按类型找事务管理器,多个候选就抛 NoUniqueBeanDefinitionException。
Spring Boot 2.1 起默认禁用同名 Bean 覆盖,业务代码与第三方 Starter 注册同名 Bean 时抛该异常。
profile 缺失或 spring.config.import 路径无效时抛 ConfigDataLocationNotFoundException。
@Transactional 标在 private 方法上既不报错也不生效,代理只能拦截穿过代理的外部调用,private 方法无法被覆盖。
Spring Boot 默认用 CGLIB 代理,final 类或方法无法被子类化,注解静默失效或抛 AopConfigException。
@Transactional 默认只回滚 RuntimeException 和 Error,抛受检异常时事务照常提交,需配 rollbackFor。
NESTED 依赖数据库保存点实现部分回滚,JPA 方言不支持 savepoint 时直接抛 TransactionSystemException。
REQUIRES_NEW 挂起外层事务并开启独立新事务,内层一旦提交,外层回滚无法撤销,产生脏数据。
Spring 只在异常穿过代理边界时才回滚,事务方法内 try-catch 捕获异常未重新抛出,代理感知不到,事务照常提交。
内层事务异常被外层 catch 吞掉后继续提交,但物理事务已标记 rollback-only,提交时抛 UnexpectedRollbackException。
Spring Boot 2.1 起默认禁用同名 Bean 覆盖,业务代码与第三方 Starter 注册同名 Bean 时抛该异常。