spring 的 核心 refresh() 方法阅读技巧
Spring 的 refresh() 方法是理解整个 IoC 容器核心逻辑的最佳入口。这个方法就像容器的“启动总纲”,定义了从加载配置到创建所有单例 Bean 的完整流程。下面我帮你把它拆解成几个易于理解的阶段,并告诉你每一步该看什么、怎么调试。
📍 一、先找到 refresh() 方法
-
所在类:
org.springframework.context.support.AbstractApplicationContext -
版本:以你正在阅读的 5.3.x 为例
-
定位技巧:在 IDEA 中双击
Shift,输入AbstractApplicationContext.refresh直接跳转
这个方法是 public void refresh() throws BeansException, IllegalStateException,它的代码结构非常清晰,由一系列具有明确职责的子方法组成。
🔍 二、宏观俯瞰:refresh() 的整体骨架
先看一眼方法的整体结构,大概有十几个步骤,但核心可以归纳为三大阶段:
-
准备阶段:为容器启动做准备(环境、监听器等)
-
BeanFactory 创建与配置阶段:加载配置、注册 BeanPostProcessor、执行 BeanFactoryPostProcessor
-
单例 Bean 实例化阶段:初始化所有剩余的单例 Bean(非懒加载)
对应的代码骨架(简化后):
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备上下文
prepareRefresh();
// 2. 获取新的 BeanFactory(通常是从新加载的配置中创建)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 对 BeanFactory 进行预填充(如设置类加载器、添加后置处理器等)
prepareBeanFactory(beanFactory);
try {
// 4. 允许子类对 BeanFactory 进行后置处理(模板方法)
postProcessBeanFactory(beanFactory);
// 5. 调用 BeanFactoryPostProcessor(重要!)
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册 BeanPostProcessor(重要!)
registerBeanPostProcessors(beanFactory);
// 7. 初始化消息源(国际化)
initMessageSource();
// 8. 初始化事件广播器
initApplicationEventMulticaster();
// 9. 模板方法:留给子类刷新特定 bean
onRefresh();
// 10. 注册监听器
registerListeners();
// 11. **核心:实例化所有非懒加载的单例 Bean**
finishBeanFactoryInitialization(beanFactory);
// 12. 最后一步:发布容器刷新完成事件
finishRefresh();
} catch (BeansException ex) {
// 异常处理:销毁已创建的 bean
destroyBeans();
cancelRefresh(ex);
throw ex;
} finally {
// 重置公共缓存
resetCommonCaches();
}
}
}
🧭 三、关键步骤拆解(建议打断点阅读)
你可以从第 1 步开始逐行 Debug ,或者直接跳到最核心的 finishBeanFactoryInitialization。但为了更好地理解上下文,建议按顺序跟踪。
1️⃣ prepareRefresh()
-
做什么:设置启动时间、激活状态、初始化属性源、验证必要属性。
-
关注点:
initPropertySources()是一个模板方法,留给子类扩展(例如 Web 环境会设置 servlet 相关属性)。 -
断点:可以放在方法内部,观察
environment的变化。
2️⃣ obtainFreshBeanFactory()
-
做什么:这是创建或刷新 BeanFactory 的地方。
-
调用链:
refreshBeanFactory()→ 如果是AbstractRefreshableApplicationContext(如 XML 或注解配置),会销毁原有的 BeanFactory,重新加载配置,创建新的DefaultListableBeanFactory,并读取所有 Bean 定义(loadBeanDefinitions)。 -
关注点:从这里开始,容器拥有了所有 Bean 的元信息(
BeanDefinition)。 -
断点:在
loadBeanDefinitions方法中,可以观察 XML 或注解是如何被解析成BeanDefinition的。
3️⃣ prepareBeanFactory(beanFactory)
-
做什么:为 BeanFactory 配置标准特性,如:
-
设置类加载器
-
添加
ApplicationContextAwareProcessor(处理 Aware 接口) -
注册一些特殊的单例 Bean(如
environment、systemProperties等)
-
-
关注点:这里注册的
BeanPostProcessor会在后续对所有 Bean 生效。
4️⃣ postProcessBeanFactory(beanFactory)
-
做什么:空方法,留给子类覆盖(例如在 Web 环境中注册 Web 相关的 Scope 或 ServletContextAwareProcessor)。
-
断点:如果你在 Web 环境下调试,可以关注子类的实现。
5️⃣ invokeBeanFactoryPostProcessors(beanFactory) ⭐️
-
做什么:调用所有注册的
BeanFactoryPostProcessor(包括BeanDefinitionRegistryPostProcessor)。 -
谁在这里执行:例如
ConfigurationClassPostProcessor(处理@Configuration类)、PropertySourcesPlaceholderConfigurer(解析占位符${...})。 -
效果:此时可以对尚未实例化的
BeanDefinition进行修改或注册新 Bean。 -
断点:观察
BeanFactoryPostProcessor的执行顺序,以及BeanDefinition的变化。
6️⃣ registerBeanPostProcessors(beanFactory) ⭐️
-
做什么:将所有实现了
BeanPostProcessor接口的 Bean 注册到 BeanFactory 的beanPostProcessors列表中。注意:这里只是注册,不会调用它们的方法。 -
顺序:先注册实现了
PriorityOrdered的,再是Ordered,最后是普通的。 -
断点:可以查看
beanPostProcessors列表的内容。
7️⃣ initMessageSource()
-
做什么:初始化国际化消息源。
-
关注点:如果容器中没有名为
messageSource的 Bean,会注册一个DelegatingMessageSource作为空实现。
8️⃣ initApplicationEventMulticaster()
-
做什么:初始化事件广播器。默认是
SimpleApplicationEventMulticaster。 -
关注点:这里决定了事件发布的方式(同步/异步)。
9️⃣ onRefresh()
-
做什么:模板方法,留给子类初始化特定的 Bean(例如 Web 容器中的
ThemeSource或内嵌 Web 服务器)。 -
断点:如果你在 Spring Boot 中调试,这里会触发
ServletWebServerApplicationContext的onRefresh(),从而启动内嵌 Tomcat。
🔟 registerListeners()
-
做什么:将容器中所有实现了
ApplicationListener的 Bean 注册到事件广播器,并可能发布早期事件。 -
关注点:可以观察监听器是如何被添加的。
1️⃣1️⃣ finishBeanFactoryInitialization(beanFactory) ⭐️⭐️⭐️
-
做什么:核心中的核心——实例化所有剩余的非懒加载单例 Bean。
-
如何实现:调用
beanFactory.preInstantiateSingletons(),该方法会遍历所有BeanDefinition,依次调用getBean()(最终触发doCreateBean)。 -
关键子步骤:
-
处理 FactoryBean(加
&前缀获取 FactoryBean 本身) -
解决循环依赖(三级缓存登场)
-
调用 BeanPostProcessor 的
postProcessBeforeInitialization和postProcessAfterInitialization -
执行
InitializingBean.afterPropertiesSet()和自定义 init-method
-
-
断点:这是最重要的断点位置。可以从
getBean开始,一路跟踪到doCreateBean,观察 Bean 的完整生命周期。
1️⃣2️⃣ finishRefresh()
-
做什么:清理资源缓存、初始化生命周期处理器、发布
ContextRefreshedEvent事件。 -
关注点:这里触发了实现了
SmartLifecycle的 Bean 的启动。
🧪 四、推荐调试路线
-
起点:在你的测试类中调用
new AnnotationConfigApplicationContext(MyConfig.class)后,立即在refresh()方法第一行打上断点。 -
逐步前进:用 F8(Step Over)逐个步骤执行,观察每个方法调用前后的变化。
-
深入核心:当执行到
finishBeanFactoryInitialization时,用 F7(Step Into)进入该方法,再进入preInstantiateSingletons(),然后观察getBean的调用。 -
观察循环依赖:如果你的测试中有循环依赖的场景,可以重点关注三级缓存(
singletonObjects、earlySingletonObjects、singletonFactories)的变化。 -
观察后置处理器:在
doCreateBean中,留意applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization的调用。
🧠 五、需要理解的设计思想
-
模板方法模式:
refresh()本身就是一个模板方法,定义了大流程,一些步骤(如postProcessBeanFactory、onRefresh)留给子类实现,以适应不同环境。 -
工厂方法模式:
obtainFreshBeanFactory()通过refreshBeanFactory()创建具体的 BeanFactory 实现。 -
观察者模式:通过事件发布/监听机制,实现容器内各组件之间的解耦。
-
策略模式:
BeanFactoryPostProcessor和BeanPostProcessor允许用户插入自定义逻辑,改变 Bean 的定义或实例化过程。
📚 六、阅读过程中可能遇到的难点
| 难点 | 解释 |
|---|---|
| 循环依赖解决 | 三级缓存 singletonFactories 是关键,理解“提前暴露”的含义。建议结合 debug 看缓存变化。 |
| BeanPostProcessor 的执行时机 | 区分两类:在 registerBeanPostProcessors 中注册,在 Bean 实例化前后执行。 |
| FactoryBean 和普通 Bean | 注意 & 前缀,理解 getObject() 的调用时机。 |
| AOP 代理的创建 | 通常由 AnnotationAwareAspectJAutoProxyCreator 在 postProcessAfterInitialization 中创建代理。 |
| 事件机制 | 事件广播器的初始化、监听器的注册、事件的发布流程。 |
💡 七、最后的小建议
-
不要试图一次性读懂所有细节:先抓住主线(Bean 的创建),再分支探索(如 AOP、事务、Web 启动)。
-
结合 Spring 官方文档:文档中对 IoC 容器的解释可以帮助你理解设计意图。
-
多画图:画出流程时序图或状态图,有助于形成整体认知。
按照这个拆解方法,相信你能够逐步攻破 refresh() 方法,从而掌握 Spring 容器的核心精髓。
更多推荐




所有评论(0)