Spring启动源码拆解与SPI原理
最近我整理了一个专门用来读 Spring 启动流程的小仓库,核心目标很简单:
把 SpringApplication.run(...) 这条主线拆开,一步一步看清楚。
仓库地址:
- GitHub: spring-run-source-walkthrough
配套视频:
这个仓库主要做了什么
这个仓库不是完整搬运 Spring 源码,也不是为了做一个业务项目。
它更像是一个“可运行 demo + 少量源码切片 + 阅读说明”的组合。
我主要做了这几件事:
- 搭了一个最小可运行的 Spring Boot demo,入口非常简单。
- 在项目里放了
MyInitializer、MyListener、spring.factories这些扩展点,方便对照启动流程看。 - 保留了 6 个和启动主线最相关的 Spring 源码文件,并在里面加了中文注释。
- 补了几篇阅读文档,把启动顺序和 SPI 关系串起来。
所以这个仓库不是“全量源码阅读仓库”,而是“围绕 run() 主线做定向拆解”的版本。
为什么只保留少量源码
一开始我也想过直接把 Spring Boot 和 Spring Framework 整套源码都放进去。
但后来发现没这个必要。
如果只是为了讲清楚启动流程,真正反复看的类其实并不多。整套源码都带上,仓库会很重,阅读时也容易分心。
最后我保留下来的核心文件是这 6 个:
SpringApplication.javaWebApplicationType.javaAbstractApplicationContext.javaDefaultListableBeanFactory.javaBeanDefinition.javaBeanPostProcessor.java
这 6 个类基本已经能把下面这些问题串起来:
run()是怎么一步步走下去的- 为什么最终会落到
refresh() BeanDefinition是怎么进容器的BeanPostProcessor在整个启动阶段处于什么位置
这个仓库怎么读
如果只想先抓主线,我觉得可以按这个顺序看:
BlueOceanApplication.javaSpringApplication构造器WebApplicationType.deduceFromClasspath()SpringApplication.run()AbstractApplicationContext.refresh()spring.factoriesMyInitializerMyListenerDefaultListableBeanFactoryBeanDefinitionBeanPostProcessor
这样看下来,主流程会比较顺。
SPI 这一块我也顺手放进去了
这个仓库里除了 Spring 启动流程,我还放了一个很小的 Java SPI 示例。
对应文件大概有这些:
MyServiceMyServiceImpl1MyServiceImpl2SpiDemoMETA-INF/services/com.blue.ocean.spi.MyService
这样做的原因也不复杂。
很多人第一次看 spring.factories 的时候,会觉得 Spring 这一套很绕。但如果先拿标准 Java SPI 过一遍,再回来看 Spring Boot 的加载方式,思路会顺很多。
也就是说,这个仓库里其实放了两条线:
ServiceLoader这条 Java SPI 线spring.factories这条 Spring 扩展线
把它们放在一起,比较容易讲清楚“它们像在哪里,不像在哪里”。
仓库里我额外补的东西
除了源码切片本身,我还补了几份说明文档,主要是为了让阅读路径更明确一点。
比如:
- 启动主线怎么走
MyInitializer和MyListener分别挂在哪个阶段- 为什么
run()不等于“直接开始创建 Bean”
这些内容如果只靠临场讲,很容易散。
落成文档之后,后面不管是自己回看,还是给别人看,都会轻松很多。
如果你也想自己读一遍 Spring 启动
我自己的建议是,先别想着一口气把 Spring 全吃掉。
先盯住这一句:
SpringApplication.run(BlueOceanApplication.class, args);
然后顺着这句往下走,把构造器、run()、refresh() 这几段连起来。
等主线有了,再去补 BeanDefinition、BeanPostProcessor、事件监听这些细节,会舒服很多。
相关链接
- GitHub 仓库: https://github.com/willorn/spring-run-source-walkthrough
- B 站视频: https://www.bilibili.com/video/BV1CN7n63EqG/?share_source=copy_web
如果你最近也在看 Spring 启动源码,这个仓库应该能省掉一点到处跳文件的时间。
