Spring 启动与加载过程

本文最后更新于 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实例化后立即放入,用于延迟创建代理

Spring 启动与加载过程
http://gadoid.io/2025/06/25/Spring-启动与加载过程/
作者
Codfish
发布于
2025年6月25日
许可协议