Spring 上下文构建源码深度解析:从 ClassPathXmlApplicationContext 到 IOC 容器就绪
Spring 上下文(ApplicationContext)是 IOC 容器的核心载体,负责配置加载、BeanDefinition 管理、Bean 实例化与初始化的全流程。以 ClassPathXmlApplicationContext 为例,其初始化过程围绕 refresh() 方法展开,这是 Spring 最核心的源码链路之一。从 “构造函数初始化→refresh() 全景流程→关键子流程拆解→核心设计思想” 四个维度,彻底讲透上下文构建的每一步。
上下文初始化入口:ClassPathXmlApplicationContext 构造函数
创建 ClassPathXmlApplicationContext 实例时,仅需一行代码,但背后触发了完整的初始化流程:
1 | ApplicationContext context = new ClassPathXmlApplicationContext("spring-lifecycle.xml"); |
构造函数核心逻辑
构造函数的本质是 “初始化配置路径 + 触发上下文刷新”,源码如下(已简化关键逻辑):
1 | // ClassPathXmlApplicationContext 构造函数 |
setConfigLocations:将配置文件路径(支持多个,用逗号分隔)解析为 Spring 可识别的资源路径(如classpath:spring-lifecycle.xml),并存储到configLocations字段;refresh():上下文初始化的 “总开关”,包含 12 个关键步骤,覆盖从 “配置加载” 到 “Bean 就绪” 的全流程。
上下文构建核心:refresh() 方法全景解析
refresh() 方法是 Spring 上下文初始化的 “主流程”,通过同步锁确保线程安全,步骤清晰且环环相扣。其核心目标是 “创建并初始化 IOC 容器,确保所有非懒加载 Bean 就绪”。
refresh() 方法完整流程(带阶段归类)
1 | public void refresh() throws BeansException, IllegalStateException { |
各阶段核心目标与关键组件
| 阶段 | 核心目标 | 关键组件 / 方法 |
|---|---|---|
| 准备阶段 | 初始化环境、校验配置 | initPropertySources()、validateRequiredProperties() |
| BeanFactory 构建 | 创建 BeanFactory 并注册 BeanDefinition | refreshBeanFactory()、loadBeanDefinitions() |
| BeanFactory 增强 | 扩展 BeanFactory 功能,处理后置处理器 | BeanFactoryPostProcessor、BeanPostProcessor |
| 基础设施初始化 | 初始化国际化、事件机制 | MessageSource、ApplicationEventMulticaster |
| Bean 实例化 | 生成非懒加载单例 Bean,处理依赖注入 | preInstantiateSingletons()、doGetBean()、三级缓存 |
| 收尾阶段 | 发布事件,标记上下文就绪 | ContextRefreshedEvent、LifecycleProcessor |
关键子流程深度拆解
refresh() 方法中,obtainFreshBeanFactory()(BeanFactory 构建)、invokeBeanFactoryPostProcessors()(后置处理器执行)、finishBeanFactoryInitialization()(Bean 实例化)是最核心的子流程,需深入源码细节。
子流程 1:obtainFreshBeanFactory()—— 创建 BeanFactory 并注册 BeanDefinition
该流程的目标是 “创建 DefaultListableBeanFactory(Spring 最核心的 BeanFactory 实现),并将 XML 配置解析为 BeanDefinition 注册到容器”。
步骤 1.1:refreshBeanFactory()—— 销毁旧工厂,创建新工厂
1 | // AbstractRefreshableApplicationContext#refreshBeanFactory |
步骤 1.2:loadBeanDefinitions()—— 解析 XML 并注册 BeanDefinition
该步骤由 XmlBeanDefinitionReader 完成,核心是 “将 XML 标签(默认标签 / 自定义标签)解析为 BeanDefinition,并注册到 BeanDefinitionRegistry”。
关键逻辑:XML 解析流程
- 创建解析器:
XmlBeanDefinitionReader关联BeanFactory,设置资源加载器(ResourceLoader)和实体解析器(EntityResolver); - 加载 XML 资源:将配置文件路径(如
spring-lifecycle.xml)转为Resource,加载为Document对象; - 解析 Document:由DefaultBeanDefinitionDocumentReader处理,区分 “默认标签” 和 “自定义标签”:
- 默认标签:Spring 内置标签(
import、alias、bean、beans),通过parseDefaultElement()解析; - 自定义标签:如
aop:aspectj-autoproxy、tx:annotation-driven,通过NamespaceHandler解析(从META-INF/spring.handlers加载映射关系)。
- 默认标签:Spring 内置标签(
示例:解析 <bean> 标签(默认标签)
1 | // DefaultBeanDefinitionDocumentReader#parseDefaultElement |
注册 BeanDefinition:存入 beanDefinitionMap
解析完成后,BeanDefinition 会被注册到 DefaultListableBeanFactory 的 beanDefinitionMap(ConcurrentHashMap<String, BeanDefinition>),键为 Bean id,值为 BeanDefinition(包含类名、属性、作用域等元信息):
1 | // DefaultListableBeanFactory#registerBeanDefinition |
子流程 2:invokeBeanFactoryPostProcessors()—— 执行 BeanFactory 后置处理器
BeanFactoryPostProcessor 是 Spring 扩展 BeanDefinition 的核心接口,作用是 “在 Bean 实例化前,修改 BeanDefinition 元信息”(如替换 ${} 占位符、动态注册 Bean)。
执行顺序规则
Spring 按优先级执行 BeanFactoryPostProcessor,确保扩展逻辑有序:
BeanDefinitionRegistryPostProcessor(子接口):优先执行,支持动态注册 BeanDefinition;- 先执行实现
PriorityOrdered接口的实例; - 再执行实现
Ordered接口的实例; - 最后执行无顺序接口的实例;
- 先执行实现
- 普通
BeanFactoryPostProcessor:后执行,仅修改已注册的 BeanDefinition;- 同样按
PriorityOrdered→Ordered→无顺序执行。
- 同样按
典型应用:PropertySourcesPlaceholderConfigurer
PropertySourcesPlaceholderConfigurer 是 BeanFactoryPostProcessor 的核心实现,负责 “替换 BeanDefinition 中的 ${key} 占位符”,流程如下:
- 加载外部配置文件(如
db.properties); - 遍历
beanDefinitionMap中的所有BeanDefinition; - 对
PropertyValues中的${key}占位符(如${db.url})替换为配置文件中的值; - 更新
BeanDefinition的属性值,确保后续实例化时属性正确。
子流程 3:finishBeanFactoryInitialization()——Bean 实例化与初始化
该流程是 “从 BeanDefinition 到可用 Bean 的最后一步”,核心是初始化所有 “非懒加载单例 Bean”,包含 “实例化→属性注入→初始化→AOP 代理” 全链路。
步骤 3.1:preInstantiateSingletons()—— 触发单例 Bean 初始化
1 | // DefaultListableBeanFactory#preInstantiateSingletons |
步骤 3.2:getBean()→doGetBean()——Bean 实例化核心逻辑
getBean() 是获取 Bean 的入口,实际逻辑在 doGetBean() 中,核心是 “从缓存获取→若不存在则创建”,并通过三级缓存解决单例 Bean 的循环依赖。
三级缓存:解决循环依赖的关键
Spring 通过三个缓存(singletonObjects、earlySingletonObjects、singletonFactories)存储不同状态的单例 Bean,避免循环依赖导致的死锁:
| 缓存名称 | 存储内容 | 作用 | 优先级(读取顺序) |
|---|---|---|---|
singletonObjects |
完全初始化完成的单例 Bean(id→Bean 实例) | 缓存就绪的 Bean,供直接获取 | 1(一级缓存) |
earlySingletonObjects |
未完成属性注入的单例 Bean(id→Bean 实例) | 提前暴露未初始化完成的 Bean,解决循环依赖 | 2(二级缓存) |
singletonFactories |
生成 Bean 的工厂(id→ObjectFactory) | 存储 Bean 的创建策略,延迟生成实例 | 3(三级缓存) |
doGetBean() 核心逻辑(简化)
1 | protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) { |
步骤 3.3:createBean()→doCreateBean()——Bean 实例化与初始化细节
createBean() 的实际逻辑在 doCreateBean() 中,包含 4 个关键步骤:
- 实例化 Bean:通过构造器 / 工厂方法创建 Bean 实例(
createBeanInstance()); - 提前暴露 Bean:将未初始化的 Bean 加入三级缓存(
singletonFactories),解决循环依赖; - 属性注入:填充 Bean 的属性(
populateBean()),处理@Autowired、<property>等注入; - 初始化 Bean:执行 Aware 回调、BeanPostProcessor 前后置处理、init-method(
initializeBean())。
initializeBean():Bean 初始化的最后一步
1 | protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) { |
- AOP 代理生成:Spring AOP 的
AnnotationAwareAspectJAutoProxyCreator是BeanPostProcessor的实现类,在applyBeanPostProcessorsAfterInitialization()中为匹配切面的 Bean 生成代理对象(JDK/CGLIB)。
核心组件与设计思想
1. 关键组件总结
| 组件 | 作用 | 核心实现类 |
|---|---|---|
BeanDefinition |
存储 Bean 元信息(类名、属性、作用域等) | RootBeanDefinition、GenericBeanDefinition |
BeanDefinitionRegistry |
注册 / 管理 BeanDefinition | DefaultListableBeanFactory |
BeanFactoryPostProcessor |
修改 BeanDefinition(实例化前) | PropertySourcesPlaceholderConfigurer、ConfigurationClassPostProcessor |
BeanPostProcessor |
增强 Bean 实例(实例化后) | AutowiredAnnotationBeanPostProcessor、AnnotationAwareAspectJAutoProxyCreator |
ApplicationContext |
上下文容器,集成 BeanFactory 与额外功能 | ClassPathXmlApplicationContext、AnnotationConfigApplicationContext |
2. 核心设计思想
- 开闭原则:通过
BeanFactoryPostProcessor、BeanPostProcessor等扩展接口,允许开发者扩展容器功能,无需修改 Spring 核心源码; - 依赖注入(DI):通过
BeanDefinition管理依赖关系,在populateBean()中自动注入,降低组件耦合; - 循环依赖解决:通过三级缓存提前暴露未初始化的 Bean,避免单例 Bean 循环依赖导致的死锁;
- 事件驱动:通过
ApplicationEventMulticaster、ApplicationListener实现事件发布与监听,解耦业务逻辑; - 懒加载与预加载:单例 Bean 默认预加载(容器启动时初始化),可通过
@Lazy延迟到首次使用时初始化,平衡启动速度与内存占用。
总结:上下文构建的核心链路
Spring ClassPathXmlApplicationContext 的构建过程,本质是 “从 XML 配置到可用 Bean 的转化链路”,可精简为 5 步:
- 配置加载:
XmlBeanDefinitionReader读取 XML,解析为BeanDefinition; - BeanDefinition 注册:将
BeanDefinition存入DefaultListableBeanFactory的beanDefinitionMap; - 容器增强:
BeanFactoryPostProcessor修改BeanDefinition,BeanPostProcessor注册到容器; - Bean 实例化:
preInstantiateSingletons()初始化非懒加载单例 Bean,通过doGetBean()调用createBean()完成 “实例化→注入→初始化→代理”; - 上下文就绪:发布
ContextRefreshedEvent,标记 IOC 容器可用