Spring Bean 生命周期与循环依赖详解

Spring Bean 生命周期与循环依赖详解

  1. Java 对象与 Spring Bean 的区别:

    • Java 对象的创建步骤:编译源码 -> 类加载到 JVM -> 初始化对象。
    • Spring Bean 使用 BeanDefinition 描述对象信息,如 @Scope@Lazy 等。
  2. Spring Bean 生命周期:

    • 扫描 Bean 信息:从 XML、注解或 JavaConfig 中读取。
    • 封装 BeanDefinition :存储到 beanDefinitionMap 中。
    • 执行 BeanFactoryPostProcessor :如 PropertyPlaceholderConfigurer 注入占位符信息。
    • 实例化 Bean:通过反射选择构造器,实例化对象,但未注入属性。
    • 属性注入 :解决依赖,如 UserService 依赖 SendService
    • 初始化工作
      • 检查是否实现了 Aware 接口,如 ApplicationContextAware 获取 ApplicationContext
      • 执行 BeanPostProcessor,如 AOP 关键的 AnnotationAwareAspectJAutoProxyCreator
      • 执行 @PostConstructInitializingBeaninit-method 等初始化方法。
    • 销毁 Bean :执行 destroy-method
  3. 循环依赖解决方案:

    • 三级缓存

      • 一级缓存singletonObjects,存储完全初始化的单例 Bean。
      • 二级缓存earlySingletonObjects,存储未完全初始化的单例 Bean。
      • 三级缓存singletonFactories,存储 Bean 工厂处理代理对象。
    • 过程

      1. 实例化 A:A 放入三级缓存。
      2. 注入 A 的属性:需要 B,实例化 B。
      3. 实例化 B:B 依赖 A,从三级缓存获取 A 的代理,将A代理对象放入二级缓存。
      4. 初始化 B:从二级缓存移至一级缓存。
      5. 返回 A:继续注入 A 的属性,完成初始化,移至一级缓存。
  4. 关键源码位置

    • AbstractApplicationContext#refresh
    • AbstractApplicationContext#finishBeanFactoryInitialization
    • ConfigurableListableBeanFactory#preInstantiateSingletons
    • AbstractBeanFactory#getBean
    • AbstractBeanFactory#doGetBean
    • DefaultSingletonBeanRegistry#getSingleton
    • AbstractAutowireCapableBeanFactory#createBean
    • AbstractAutowireCapableBeanFactory#doCreateBean
    • AbstractAutowireCapableBeanFactory#createBeanInstance
    • DefaultSingletonBeanRegistry#addSingletonFactory
    • AbstractAutowireCapableBeanFactory#populateBean
    • AbstractAutowireCapableBeanFactory#initializeBean

总结:

  • Spring 使用 BeanDefinition 管理 Bean 的元数据。
  • Bean 实例化和属性注入分开进行。
  • 生命周期中提供了多种扩展点,如 BeanFactoryPostProcessor、Aware 接口、BeanPostProcessor 和初始化方法。
  • 三级缓存解决循环依赖问题,通过 ObjectFactory 处理代理对象。
相关推荐
大模型玩家七七1 小时前
基于语义切分 vs 基于结构切分的实际差异
java·开发语言·数据库·安全·batch
Coder_Boy_2 小时前
技术发展的核心规律是「加法打底,减法优化,重构平衡」
人工智能·spring boot·spring·重构
牛奔2 小时前
Go 如何避免频繁抢占?
开发语言·后端·golang
寻星探路6 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
想用offer打牌7 小时前
MCP (Model Context Protocol) 技术理解 - 第二篇
后端·aigc·mcp
曹牧8 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
KYGALYX8 小时前
服务异步通信
开发语言·后端·微服务·ruby
掘了8 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
爬山算法9 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate