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 容器的核心精髓。