You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Security AuthenticationManager Bean创建异常排查求助

Spring启动时authenticationManager Bean重复创建失败问题排查

我用FlightRecorderApplicationStartup分析Spring应用启动过程,发现大量spring.beans.instantiate事件都关联org.springframework.security.authenticationManager Bean,每次触发都会抛出BeanCurrentlyInCreationException,提示该Bean正处于创建中,怀疑存在无法解析的循环引用或异步初始化依赖。这类事件多达数百个,且共享同一个parentId(对应我自定义的某个Bean的spring.beans.instantiate事件)。目前应用可正常启动,但Spring反复创建该Bean失败的流程并不合理,需明确以下问题:

  1. Spring为何会记录该问题并绕过它?
  2. 如何排查该问题?
  3. 若为循环依赖,如何识别依赖链中的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 17:02:49