Spring Security AuthenticationManager Bean创建异常排查求助
authenticationManager Bean重复创建失败问题排查 我用FlightRecorderApplicationStartup分析Spring应用启动过程,发现大量spring.beans.instantiate事件都关联org.springframework.security.authenticationManager Bean,每次触发都会抛出BeanCurrentlyInCreationException,提示该Bean正处于创建中,怀疑存在无法解析的循环引用或异步初始化依赖。这类事件多达数百个,且共享同一个parentId(对应我自定义的某个Bean的spring.beans.instantiate事件)。目前应用可正常启动,但Spring反复创建该Bean失败的流程并不合理,需明确以下问题:
- Spring为何会记录该问题并绕过它?
- 如何排查该问题?
- 若为循环依赖,如何识别依赖链中的Bean?
已知@Lazy可作为解决方案,但无法定位循环路径。当前使用版本:
- Spring Framework: 6.2.2
- Spring Security: 6.4.2
一、Spring记录并绕过该问题的原因
Spring在Bean创建过程中会维护创建中Bean缓存池(singletonsCurrentlyInCreation集合)。当尝试获取一个正处于创建中的Bean时,若属于以下场景会抛出BeanCurrentlyInCreationException:
- 单例Bean的构造器注入循环依赖(Spring默认不支持该场景)
- 无法通过三级缓存解决的循环依赖场景
但并非所有这类异常都会导致启动失败:
- 如果是**依赖查找(而非依赖注入)**触发的获取操作(比如代码中手动调用
ApplicationContext.getBean()),Spring会捕获异常并返回null或跳过操作,避免阻断整个启动流程。 - 部分Spring内部组件(如Security的自动配置逻辑)在探测Bean状态时,会主动尝试获取Bean,即使失败也会 fallback 到备用逻辑,因此会出现大量失败记录但应用仍能启动的情况。
二、排查问题的具体步骤
1. 开启Bean创建详细日志
添加日志配置,打印Bean创建的完整流程,重点关注authenticationManager和parentId对应的自定义Bean:
logging.level.org.springframework.beans.factory=TRACE logging.level.org.springframework.security.authentication=TRACE
通过日志可查看每次尝试创建authenticationManager的触发源,以及具体的依赖加载顺序。
2. 分析FlightRecorder事件链
通过parentId关联到你的自定义Bean,检查该Bean的创建流程中哪一步触发了authenticationManager的获取操作:
- 查看该自定义Bean的所有依赖项,确认是否直接或间接依赖
authenticationManager - 检查该Bean的初始化方法(
@PostConstruct、InitializingBean)或构造器中,是否存在手动获取authenticationManager的代码
3. 排查Spring Security自动配置冲突
Spring Security的AuthenticationManager通常由自动配置生成,若你自定义了相关Bean(如UserDetailsService、AuthenticationProvider),可能触发自动配置逻辑冲突:
- 检查是否存在多个
AuthenticationManager类型的Bean - 确认是否通过
@EnableWebSecurity等注解自定义了Security配置类,其中是否有提前获取AuthenticationManager的代码
三、识别循环依赖链的方法
1. 利用Spring循环依赖检测日志
在Spring 6.x中,开启DEBUG级别日志即可查看循环依赖的详细链路:
logging.level.org.springframework.beans.factory.support.DefaultListableBeanFactory=DEBUG
日志中会出现类似Circular reference involving bean 'xxx'的提示,明确列出循环的Bean链。
2. 手动梳理依赖关系
- 找到parentId对应的自定义Bean,列出它的所有依赖(构造器注入、字段注入、方法注入的Bean)
- 依次列出这些依赖Bean的依赖项,直到找到回指向
authenticationManager或自定义Bean的节点 - 重点关注构造器注入的依赖,因为Spring默认不支持构造器循环依赖,这类场景最容易触发
BeanCurrentlyInCreationException
3. 使用IDEA依赖分析工具
若使用IDEA开发,可通过View > Tool Windows > Maven > Dependencies查看Bean依赖关系,或使用Analyze > Analyze Dependencies功能直接查找循环依赖路径。
四、定位@Lazy的适用位置
找到循环依赖链后,在链中任意一个依赖注入点添加@Lazy,即可延迟Bean初始化、打破循环:
- 构造器注入循环:在构造器参数上添加
@Lazy - 字段/方法注入循环:在字段或方法参数上添加
@Lazy
示例代码:
public class CustomBean { private final AuthenticationManager authenticationManager; public CustomBean(@Lazy AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } }
内容的提问来源于stack exchange,提问作者user1209455

