Spring 源码学习-Spring创建Bean对象的主流程
大约 3 分钟

流程图核心步骤梳理
根据图示信息,Spring创建Bean的核心流程可分为以下六大阶段,结合三级缓存机制与源码实现,具体流程如下:
1. 配置加载与解析
图示步骤:加载XML
→ 解析XML
→ 生成BeanDefinition
源码实现:
- 入口:
ClassPathXmlApplicationContext
初始化时触发refresh()
- 关键类:
XmlBeanDefinitionReader
:读取XML文件BeanDefinitionParserDelegate
:解析<bean>
标签
- 生成结果:
每个<bean>
标签解析为一个BeanDefinition
对象,包含:
class name: "com.example.UserService"
scope: "singleton"
property values: {dataSource → ref="dataSource"}
2. BeanDefinition注册
图示步骤:封装
→ 放到容器中
(对应图中K:String, V:BeanDefinition
)
源码实现:
- 注册位置:
DefaultListableBeanFactory
内部的beanDefinitionMap
// Key: Bean名称(String), Value: BeanDefinition对象
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
- 触发时机:
在refresh()
的obtainFreshBeanFactory()
阶段完成注册
3. Bean实例化(核心阶段)
图示步骤:实例化
→ 放到容器中
(对应图中K:Class, V:Object
)
源码关键路径:
// AbstractAutowireCapableBeanFactory
protected Object doCreateBean(...) {
// 3.1 实例化对象(反射/CGLIB)
Object instance = createBeanInstance(beanName, mbd, args);
// 3.2 提前暴露早期引用(解决循环依赖)
addSingletonFactory(beanName, () -> getEarlyBeanReference(...));
// 3.3 属性注入(DI)
populateBean(beanName, mbd, instanceWrapper);
// 3.4 初始化(Aware接口、@PostConstruct等)
initializeBean(beanName, instance, mbd);
// 3.5 完成创建,放入一级缓存
registerSingleton(beanName, instance);
}
4. 三级缓存机制(解决循环依赖)
图示标注:三级缓存
、K:String, V:ObjectFactory
三级缓存结构:
缓存名称 | 存储内容 | 作用阶段 |
---|---|---|
singletonFactories | ObjectFactory(工厂对象) | 实例化后,初始化前 |
earlySingletonObjects | 早期引用(未完成初始化的对象) | 属性注入阶段 |
singletonObjects | 完整Bean(已初始化) | 初始化完成后 |
流程示例(A依赖B,B依赖A):
- 创建A时,实例化后将其ObjectFactory放入
singletonFactories
- 填充A的属性时发现需要B,触发B的创建
- 创建B时同样将ObjectFactory放入
singletonFactories
- 填充B的属性时从
singletonFactories
获取A的ObjectFactory,生成A的早期引用 - B完成初始化后放入
singletonObjects
,A继续完成初始化
5. 容器存储与获取
图示步骤:从容器中获取
→ K:Class, V:Object
源码实现:
- 存储位置:
DefaultSingletonBeanRegistry
的单例池
// Key: Bean名称, Value: 完整Bean实例
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
- 获取方式:
// ApplicationContext接口方法
UserService userService = context.getBean("userService", UserService.class);
6. 完整流程总结
- 配置加载:XML → BeanDefinition
- 注册定义:beanDefinitionMap存储Bean元数据
- 实例化:
- 反射/CGLIB创建对象
- 提前暴露ObjectFactory(三级缓存)
- 依赖注入:
- 解析@Autowired/@Resource等注解
- 通过三级缓存解决循环依赖
- 初始化:
- 调用Aware接口(BeanNameAware等)
- 执行@PostConstruct和init-method
- 容器存储:单例池(singletonObjects)存储完整Bean
- 获取使用:通过getBean()从容器获取实例
流程图与源码的对应关系
图示步骤 | 对应源码方法/类 | 技术要点 |
---|---|---|
加载XML | XmlBeanDefinitionReader.loadBeanDefinitions() | 解析XML的SAX事件模型 |
生成BeanDefinition | BeanDefinitionParserDelegate.parseBeanDefinitionElement() | Bean元数据抽象 |
实例化 | AbstractAutowireCapableBeanFactory.createBeanInstance() | 反射 vs CGLIB策略选择 |
三级缓存 | DefaultSingletonBeanRegistry.getSingleton() | 循环依赖的“先暴露后完善”机制 |
放到容器中 | DefaultSingletonBeanRegistry.addSingleton() | 单例池的线程安全ConcurrentHashMap |
学习建议
- 调试技巧:在
AbstractApplicationContext.refresh()
设置断点,观察BeanDefinition加载过程 - 关键日志:启用Spring调试日志查看Bean生命周期事件
logging.level.org.springframework.beans=DEBUG
- 实践验证:通过以下代码验证循环依赖解决流程:
// 定义两个相互依赖的Bean
@Service
public class A {
@Autowired private B b;
}
@Service
public class B {
@Autowired private A a;
}
通过此流程图,可清晰看到Spring如何将XML配置转化为可用的Java对象,并解决复杂的依赖关系问题。这是理解Spring IoC容器设计精髓的关键路径。