Spring 启动流程:比喻表达

Spring 启动流程:从零到一的故事

Spring 的启动流程(以 AnnotationConfigApplicationContext 为例)就像一个工厂从空地到生产线的搭建过程。面试中常被问到这个流程,但记不住怎么办?让我们用一条逻辑链条,把它讲成一个故事,帮助你记住每个步骤。

时序图:故事的蓝图

先看一张简化的时序图(用 Mermaid 语法,可在 Mermaid Live Editor 渲染):

sequenceDiagram participant U as 用户 participant AC as ApplicationContext participant BF as BeanFactory participant BFP as BeanFactoryPostProcessor participant BPP as BeanPostProcessor participant EM as EventMulticaster participant EL as Listener participant BEAN as Bean U->>AC: new ApplicationContext(AppConfig) AC->>AC: refresh() AC->>BF: 创建并配置工厂 BF->>BFP: 调整蓝图 BF->>BPP: 准备生产线工人 AC->>EM: 搭建广播站 EM->>EL: 招募听众 BF->>BEAN: 生产产品 AC->>EM: 宣布开业 U-->>AC: 工厂运行

故事线:Spring 工厂的诞生

想象你是一个工厂老板,要用 Spring 建一个智能工厂。以下是整个流程的逻辑链条:

1. 开工:创建工厂大门 (new ApplicationContext)

  • 代码new AnnotationConfigApplicationContext(AppConfig.class)
  • 故事 :你买了块地,立了个牌子"Spring 工厂",大门上写着配置信息(AppConfig)。
  • 细节 :初始化了一个空的 ApplicationContext,准备进入正题。

2. 总指挥:启动工厂 (refresh())

  • 疑问 :为什么要 refresh()?有什么深意?
  • 故事 :你按下启动按钮(refresh()),工厂开始从零到一地搭建。
  • 深意refresh() 是总指挥,负责把所有零件(Bean 定义、事件系统等)组装成一个完整的工厂。它确保一切按顺序发生,避免混乱。
  • 细节 :这是 AbstractApplicationContext 的核心方法,包含以下所有步骤。

3. 建厂房:创建并配置 BeanFactory

  • 步骤
    1. obtainFreshBeanFactory() :建好厂房框架(DefaultListableBeanFactory),画出生产蓝图(扫描 @Component,注册 BeanDefinition)。
    2. prepareBeanFactory():装修厂房,装上设备(类加载器、处理器)。
  • 疑问 :为什么要忽略 Aware 接口?我不是要用它们吗?
  • 故事 :你告诉工人,别直接把"厂长须知"(BeanNameAwareBeanFactoryAware 等)贴在墙上,而是交给专门的助手(BeanPostProcessor)在合适时发给产品。
  • 细节 :忽略 Aware 接口是为了避免自动注入,由 ApplicationContextAwareProcessor 在初始化时手动设置,确保控制权在框架。

4. 改蓝图:BeanFactoryPostProcessor

  • 步骤invokeBeanFactoryPostProcessors()
  • 故事 :设计师(ConfigurationClassPostProcessor)跑来说,蓝图得改,增加 @Configuration@Bean 的生产线。
  • 细节 :动态调整 BeanDefinition,为后续生产做准备。

5. 招工人:BeanPostProcessor

  • 步骤registerBeanPostProcessors()
  • 疑问BeanPostProcessor 是什么?我用过 @Order 是干嘛的?
  • 故事 :你招了一群质检员(BeanPostProcessor),他们会在产品生产后检查和加工(比如 AOP 包装、设置 Aware)。用 @Order 排好他们的顺序,比如先检查再包装。
  • 细节BeanPostProcessor 在 Bean 初始化前后介入,AOP 和 Aware 都靠它实现。

6. 搭广播站:事件系统

  • 步骤
    1. initMessageSource():装个翻译机(国际化)。
    2. initApplicationEventMulticaster() :建广播站(ApplicationEventMulticaster)。
    3. registerListeners() :招募听众(ApplicationListener)。
  • 疑问 :事件是什么?ApplicationListener 怎么理解?
  • 故事 :你建了个广播站,发布消息(事件,如 ContextRefreshedEvent),听众(ApplicationListener)听到后做事,比如记录日志。
  • 细节 :事件是 ApplicationEvent 的实例,广播站分发给监听器,解耦逻辑。

7. 加设备:onRefresh()

  • 疑问onRefresh() 干嘛用?不是已经 refresh() 了吗?
  • 故事:工厂基本建好,但你想加个特殊设备(比如 Spring Boot 的 Web 服务器),就在这步装上。
  • 细节onRefresh() 是子类的扩展点,不是"重新刷新",而是特定场景的初始化。

8. 生产产品:finishBeanFactoryInitialization()

  • 步骤preInstantiateSingletons()
  • 疑问 :过程不够详细,三级缓存和 Aware 呢?
  • 故事 :生产线启动,生产单例产品(Bean):
    1. 拿零件:实例化对象。
    2. 组装:依赖注入,用三级缓存解决循环依赖(一级存成品,二级存半成品,三级存加工厂)。
    3. 质检 :调用 Aware(如 setBeanName)、@PostConstruct、初始化方法。
    4. 包装:AOP 代理。
  • 细节 :三级缓存确保循环依赖不出错,BeanPostProcessor 处理 Aware 和代理。

9. 开业:finishRefresh()

  • 步骤 :发布 ContextRefreshedEvent
  • 疑问ContextRefreshedEvent 是什么?事件有实体吗?
  • 故事 :工厂完工,你通过广播站喊:"开业啦!"(ContextRefreshedEvent),听众鼓掌。
  • 细节ContextRefreshedEvent 是具体的事件类,代码是 new ContextRefreshedEvent(this),通知容器就绪。

逻辑链条:一句话总结

  • 开工(new)→ 指挥(refresh)→ 建厂(BeanFactory)→ 改图(BFP)→ 招工(BPP)→ 广播(事件)→ 加装(onRefresh)→ 生产(Bean)→ 开业(finish)

常见面试问题

  1. 为什么要 refresh()?
    • 它是总指挥,把工厂从零建到运行。
  2. BeanPostProcessor 干嘛用?
    • 在 Bean 生产后加工,比如 AOP 和 Aware。
  3. 三级缓存是啥?
    • 解决循环依赖的三个"仓库":成品、半成品、加工厂。

总结

通过这个"建工厂"的故事,Spring 的启动流程不再是零散的步骤,而是一个连贯的链条。记住这条线,面试时就能娓娓道来!

相关推荐
景天科技苑2 小时前
【Rust通用集合类型】Rust向量Vector、String、HashMap原理解析与应用实战
开发语言·后端·rust·vector·hashmap·string·rust通用集合类型
小钻风巡山4 小时前
springboot 视频分段加载在线播放
java·spring boot·后端
豌豆花下猫4 小时前
Python 潮流周刊#100:有了 f-string,为什么还要 t-string?(摘要)
后端·python·ai
小黑随笔4 小时前
【Golang玩转本地大模型实战(一):ollma部署模型及流式调用】
开发语言·后端·golang
江沉晚呤时4 小时前
Redis缓存穿透、缓存击穿与缓存雪崩:如何在.NET Core中解决
java·开发语言·后端·算法·spring·排序算法
光影少年6 小时前
新手学编程前端好还是后端
前端·后端
why1516 小时前
百度网盘golang实习面经
开发语言·后端·golang
hac13228 小时前
SpringBoot多环境配置
java·spring boot·后端
Go高并发架构_王工11 小时前
GoFrame框架深度解析:grpool的优势、最佳实践与踩坑经验
服务器·后端·golang
exe45212 小时前
4 月 28 日项目进展与规划会议纪要
后端