源码分析之上下文构建
Spring 上下文构建源码深度解析:从 ClassPathXmlApplicationContext 到 IOC 容器就绪
Spring 上下文(ApplicationContext)是 IOC 容器的核心载体,负责配置加载、BeanDefinition 管理、Bean 实例化与初始化的全流程。以 ClassPathXmlApplicationContext 为例,其初始化过程围绕 refresh() 方法展开,这是 Spring 最核心的源码链路之一。从 “构造函数初始化→refresh() 全景流程→关键子流程拆解→核心设计思想” 四个维度,彻底讲透上下文构建的每一步。
上下文初始化入口:ClassPathXmlApplicationContext 构造函数
创建 ClassPathXmlApplicationContext 实例时,仅需一行代码,但背后触发了完整的初始化流程:
ApplicationContext context = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
构造函数核心逻辑
构造函数的本质是 “初始化配置路径 + 触发上下文刷新”,源码如下(已简化关键逻辑):
// ClassPathXmlApplicationContext 构造函数
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) {
super(parent); // 初始化父上下文(若有)
setConfigLocations(configLocations); // 1. 保存配置文件路径(如 "spring-lifecycle.xml")
if (refresh) {
refresh(); // 2. 核心:触发上下文刷新(IOC 容器初始化的入口)
}
}
setConfigLocations:将配置文件路径(支持多个,用逗号分隔)解析为 Spring 可识别的资源路径(如classpath:spring-lifecycle.xml),并存储到configLocations字段;refresh():上下文初始化的 “总开关”,包含 12 个关键步骤,覆盖从 “配置加载” 到 “Bean 就绪” 的全流程。
上下文构建核心:refresh() 方法全景解析
refresh() 方法是 Spring 上下文初始化的 “主流程”,通过同步锁确保线程安全,步骤清晰且环环相扣。其核心目标是 “创建并初始化 IOC 容器,确保所有非懒加载 Bean 就绪”。
refresh() 方法完整流程(带阶段归类)
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) { // 同步锁:防止并发刷新
// ========================= 阶段1:准备阶段 =========================
prepareRefresh(); // 1. 初始化环境、校验配置、记录启动状态
// ========================= 阶段2:BeanFactory 构建 =========================
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 2. 创建/刷新 BeanFactory,注册 BeanDefinition
// ========================= 阶段3:BeanFactory 增强 =========================
prepareBeanFactory(beanFactory); // 3. 填充 BeanFactory 功能(类加载器、SPEL、属性编辑器等)
try {
postProcessBeanFactory(beanFactory); // 4. 子类扩展:BeanFactory 后置处理(空方法,供自定义)
invokeBeanFactoryPostProcessors(beanFactory); // 5. 执行 BeanFactoryPostProcessor(修改 BeanDefinition)
registerBeanPostProcessors(beanFactory); // 6. 注册 BeanPostProcessor(增强 Bean 实例)
// ========================= 阶段4:上下文基础设施初始化 =========================
initMessageSource(); // 7. 初始化国际化消息源
initApplicationEventMulticaster(); // 8. 初始化事件广播器
onRefresh(); // 9. 子类扩展:初始化特殊 Bean(如 Spring MVC 的 DispatcherServlet)
registerListeners(); // 10. 注册事件监听器
// ========================= 阶段5:Bean 实例化与初始化 =========================
finishBeanFactoryInitialization(beanFactory); // 11. 初始化所有非懒加载单例 Bean
// ========================= 阶段6:收尾阶段 =========================
finishRefresh(); // 12. 发布刷新完成事件,标记上下文就绪
} catch (BeansException ex) {
// 异常处理:销毁已创建的 Bean,重置状态
destroyBeans();
cancelRefresh(ex);
throw ex;
} finally {
resetCommonCaches(); // 清理缓存(如反射缓存)
}
}
}
各阶段核心目标与关键组件
| 阶段 | 核心目标 | 关键组件 / 方法 |
|---|---|---|
| 准备阶段 | 初始化环境、校验配置 | 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()—— 销毁旧工厂,创建新工厂
// AbstractRefreshableApplicationContext#refreshBeanFactory
protected final void refreshBeanFactory() throws BeansException {
// 1. 若已有 BeanFactory,先销毁并关闭(防止重复初始化)
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 2. 创建 DefaultListableBeanFactory(实现 BeanDefinitionRegistry,支持注册 BeanDefinition)
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId()); // 设置序列化 ID,支持跨容器序列化
// 3. 定制 BeanFactory:允许 BeanDefinition 覆盖、支持循环依赖
customizeBeanFactory(beanFactory);
// 4. 核心:加载 XML 配置,生成 BeanDefinition 并注册
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory; // 保存新工厂到上下文
} catch (IOException ex) {
throw new ApplicationContextException("加载配置文件失败", ex);
}
}
步骤 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> 标签(默认标签)
// DefaultBeanDefinitionDocumentReader#parseDefaultElement
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { // 处理 <import> 标签(导入其他 XML)
importBeanDefinitionResource(ele);
} else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { // 处理 <alias> 标签(Bean 别名)
processAliasRegistration(ele);
} else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { // 处理 <bean> 标签(核心)
processBeanDefinition(ele, delegate); // 解析 <bean> 为 BeanDefinition 并注册
} else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // 处理 <beans> 标签(嵌套配置)
doRegisterBeanDefinitions(ele);
}
}
注册 BeanDefinition:存入 beanDefinitionMap
解析完成后,BeanDefinition 会被注册到 DefaultListableBeanFactory 的 beanDefinitionMap(ConcurrentHashMap<String, BeanDefinition>),键为 Bean id,值为 BeanDefinition(包含类名、属性、作用域等元信息):
// DefaultListableBeanFactory#registerBeanDefinition
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
// 1. 校验 BeanDefinition(如 methodOverrides、factoryMethodName 合法性)
((AbstractBeanDefinition) beanDefinition).validate();
// 2. 处理 BeanDefinition 覆盖(若已存在同 id 的 BeanDefinition,判断是否允许覆盖)
BeanDefinition oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException("Bean id 重复:" + beanName);
}
this.beanDefinitionMap.put(beanName, beanDefinition); // 覆盖旧定义
} else {
// 3. 新 BeanDefinition 注册(线程安全处理)
if (hasBeanCreationStarted()) {
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName); // 记录 Bean id 列表
}
} else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
}
}
}
子流程 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 初始化
// DefaultListableBeanFactory#preInstantiateSingletons
public void preInstantiateSingletons() throws BeansException {
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // 所有 Bean id 列表
// 遍历所有 BeanDefinition,初始化非懒加载单例
for (String beanName : beanNames) {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 仅初始化:非抽象、单例、非懒加载的 Bean
if (!mbd.isAbstract() && mbd.isSingleton() && !mbd.isLazyInit()) {
// 处理 FactoryBean:先初始化 FactoryBean 本身,再通过 getObject() 生成目标 Bean
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit();
if (isEagerInit) {
getBean(beanName); // 初始化目标 Bean
}
} else {
getBean(beanName); // 普通 Bean:调用 getBean() 触发实例化
}
}
}
}
步骤 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() 核心逻辑(简化)
protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) {
final String beanName = transformedBeanName(name); // 处理 FactoryBean 的 & 前缀
Object bean;
// 1. 从三级缓存获取已存在的 Bean(优先一级缓存)
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); // 处理 FactoryBean
} else {
// 2. 检查循环依赖(原型 Bean 循环依赖直接报错)
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 3. 初始化依赖的 Bean(若当前 Bean 依赖其他 Bean,先初始化依赖)
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
getBean(dep); // 先初始化依赖的 Bean
}
}
// 4. 根据作用域创建 Bean(单例/原型/其他)
if (mbd.isSingleton()) {
// 单例 Bean:通过 ObjectFactory 创建,加入三级缓存
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args); // 核心:创建 Bean 实例
} catch (BeansException ex) {
destroySingleton(beanName); // 创建失败,销毁已创建的实例
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
// 原型 Bean:每次 getBean() 都创建新实例
Object prototypeInstance = createBean(beanName, mbd, args);
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
}
return (T) bean;
}
步骤 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 初始化的最后一步
protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
// 1. Aware 接口回调:注入容器服务(如 BeanNameAware、ApplicationContextAware)
invokeAwareMethods(beanName, bean);
// 2. BeanPostProcessor 前置处理:初始化前增强(如 @PostConstruct 执行)
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
// 3. 执行初始化方法:@PostConstruct → InitializingBean#afterPropertiesSet → init-method
invokeInitMethods(beanName, wrappedBean, mbd);
// 4. BeanPostProcessor 后置处理:初始化后增强(AOP 代理生成在此处)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
- 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 容器可用