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

Spring Boot中@Configuration与@Component引发循环依赖差异的Bean构造解析

@Configuration vs @Component:Bean构造流程差异导致循环依赖的原因解析

核心区别:@Configuration类是被代理的

Spring对标注了@Configuration的类会生成CGLIB代理,而@Component只是普通的Bean实例,这是两种场景行为天差地别的根本原因。

用@Configuration时的循环依赖触发全过程

  1. Spring启动时,先创建MessageSourceConfig的原始对象,紧接着要为它生成CGLIB代理。
  2. 执行@PostConstruct方法:此时代理还没完全生成好,如果方法里间接调用了本类的messageSource()@Bean方法,代理会试图从容器里拿这个Bean——但容器里还没这个Bean呢。
  3. 执行afterPropertiesSet方法:这个方法直接调用messageSource(),因为是代理类,这个调用会被Spring拦截,强制触发messageSource Bean的创建流程。
  4. 循环依赖炸了:创建messageSource的时候,可能需要依赖MessageSourceConfig本身(比如@Bean方法里用到了配置类的属性),但此时MessageSourceConfig还卡在初始化流程里(代理没生成完、初始化方法还在跑),容器检测到循环依赖,而默认是禁用循环依赖的,直接抛出异常。

换成@Component后的正常运行流程

  1. Spring直接实例化MessageSourceConfig作为普通Bean,不会生成代理。
  2. 执行@PostConstruct和afterPropertiesSet时,调用messageSource()就是普通的Java方法调用,只是返回一个new出来的对象,不会触发Spring的Bean创建逻辑。
  3. 等MessageSourceConfig完全初始化完成后,Spring才会通过后置处理器扫描类里的@Bean注解,单独去创建messageSource Bean。这时候配置类已经是可用状态了,就算messageSource依赖它,也不会有循环依赖的问题。

关键细节提醒

  • @Configuration的代理作用:所有@Bean方法的调用都会被代理拦截,确保返回的是容器里的单例Bean,而不是每次调用都new一个新对象。但这种拦截在Bean初始化阶段就会触发Bean创建,很容易搞出循环依赖。
  • @Component下的@Bean处理:Spring是在Bean初始化完成后,才去扫描类里的@Bean方法并注册Bean定义,这时候调用@Bean方法就是普通方法,不会被拦截,也不会提前触发Bean创建。

内容的提问来源于stack exchange,提问作者PhongPhamIUH

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 00:33:10