本文最后更新于 2025年6月25日 下午
Spring 本身是一套为服务提供管理和扩展的JAVA框架。为所有纳入它管理的对象(Bean) 提供注入,增强,初始化,生命周期管理等功能。其简单调用过程如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| [BeanDefinition] 通过注解/XML 声明的类的描述信息 ↓ [createBean()] 创建ApplicationContext,由容器创建Bean对象 ↓ [instantiateBean() → InstantiationStrategy.instantiate()] 创建裸对象 ↓ [生成裸对象] 创建了目标Bean对象,但是Bean对象中的属性未初始化 ↓ [加入三级缓存 (ObjectFactory)] 创建后将自己暴露到三级缓存中,通过ObjectFactory可以获取到处于创建过程中引用对象 ↓ [属性填充 populateBean()] 向Bean中进行注入 ↓ [BeanPostProcessor → AOP代理封装] 这一步将裸对象封装为动态代理,提供功能增强 ↓ [放入一级缓存] Bean完成初始化
|
循环依赖场景下的 Spring Bean 创建完整流程
Bean创建入口
1 2 3 4 5 6 7 8
| ↓ 一级缓存 singletonObjects: 【最终对象】 → 检查是否存在? ↓ 二级缓存 earlySingletonObjects: 【早期对象】 → 检查是否存在? ↓ 三级缓存 singletonFactories: 【延迟工厂 ObjectFactory】 → 检查是否存在? ↓ 【缓存都没有 → 开始实例化】
|
doCreateBean(beanName) 流程
1 2 3 4 5 6 7 8 9
| 1. 实例化裸对象 newInstance() → 裸对象 A@100 诞生(堆上地址) ↓ 2. 注册三级缓存 singletonFactories.put(beanName, () -> getEarlyBeanReference(beanName, A@100)) → 延迟执行的代理工厂 ↓ 3. 开始属性填充 populateBean() → 如果此时依赖了B,递归 getBean(B)
|
在B初始化时 getBean(A) 逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| B → getBean(A) ↓ 一级缓存未命中 ↓ 二级缓存未命中 ↓ 三级缓存命中 → 执行 ObjectFactory → getEarlyBeanReference(beanName, A@100) → 判断是否需要AOP增强 → 若需要 → 创建代理对象 Proxy(A)@300 → 若不需要 → 返回 A@100 ↓ 把返回对象放入二级缓存 earlySingletonObjects.put(beanName, reference)
|
B 初始化完成 → 一级缓存
1 2 3 4 5
| B 属性填充完成 ↓ 执行 BeanPostProcessor 初始化逻辑 ↓ 进入一级缓存 singletonObjects.put("B", 完整B对象)
|
A 继续完成初始化
1 2 3 4 5 6 7 8 9 10 11 12
| A 继续属性填充,填入刚创建好的 B ↓ 执行完整初始化 initializeBean() ↓ 进入 postProcessAfterInitialization() → 二次判断是否已有代理(提前暴露已处理时) 是 → 直接返回已有代理 否 → 再次增强生成代理 ↓ 最终确定完整对象引用(裸对象或代理对象) ↓ 进入一级缓存 singletonObjects.put("A", 最终A对象)
|
我们可以分析出 Spring 三级缓存 所存储内容的阶段
| 缓存级别 |
变量名 |
存储内容 |
作用时机 |
| 一级缓存 |
singletonObjects |
完全初始化的Bean对象(最终对象) |
Bean完成所有初始化步骤后 |
| 二级缓存 |
earlySingletonObjects |
提前暴露的Bean对象(早期对象) |
解决循环依赖时,从三级缓存提升而来 |
| 三级缓存 |
singletonFactories |
ObjectFactory工厂对象 |
Bean实例化后立即放入,用于延迟创建代理 |