下面我按真实工程视角把 Spring Boot 的生命周期完整梳理一遍,不讲空概念,直接对应你在写后端、调试、排错时到底发生了什么。
⸻
一句话总览(先给你一个"时间轴感")
JVM 启动 → SpringApplication 启动 → 创建 ApplicationContext → 扫描 Bean → Bean 实例化 & 注入 → 容器刷新完成 → Web 服务器启动 → 应用可用 → 运行中 → 关闭容器
⸻
一、应用启动阶段(main 方法开始)
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
这一行背后干了什么?
-
创建 SpringApplication 对象
-
推断应用类型
• Servlet(最常见)
• Reactive
• None
- 加载:
• ApplicationContextInitializer
• ApplicationListener
- 设置环境 Environment(profiles、配置文件)
⚠️ 这一步还没创建任何 Bean
⸻
二、准备阶段(Environment & Context 准备)
1️⃣ 创建并准备 Environment
加载配置源(优先级很关键):
-
命令行参数
-
application.yml / properties
-
系统环境变量
-
JVM 参数
👉 你在 @Value、@ConfigurationProperties 能拿到值,依赖的就是这一步
⸻
2️⃣ 创建 ApplicationContext
根据 Web 类型:
• AnnotationConfigServletWebServerApplicationContext
• AnnotationConfigApplicationContext
⚠️ 此时容器已创建,但还没装 Bean
⸻
三、核心阶段:容器刷新(最关键)
真正的 Spring 生命周期从这里开始
核心方法:
AbstractApplicationContext#refresh()
⸻
① Bean 定义加载(扫描)
• 扫描:
• @Component
• @Service
• @Repository
• @Controller
• @Configuration
• 解析:
• @Bean
• @Import
• @Conditional
📌 这一步只是 注册 BeanDefinition
📌 没有 new 对象
⸻
② BeanFactoryPostProcessor 阶段
发生在 实例化之前
典型代表:
• ConfigurationClassPostProcessor
• PropertySourcesPlaceholderConfigurer
👉 能改 Bean 定义
👉 不能拿到 Bean 实例
⸻
③ Bean 实例化 & 依赖注入(重点)
对每个 Bean(默认单例):
生命周期顺序(非常重要)
-
构造方法
-
@Autowired / 构造器注入
-
Aware 接口回调
• BeanNameAware
• ApplicationContextAware
-
BeanPostProcessor#postProcessBeforeInitialization
-
@PostConstruct
-
InitializingBean.afterPropertiesSet()
-
自定义 init-method
-
BeanPostProcessor#postProcessAfterInitialization
📌 AOP 代理对象在这一步产生
⸻
④ 容器刷新完成
• 发布 ContextRefreshedEvent
• Spring 容器进入 可用状态
⸻
四、Web 环境专属阶段(Spring Boot 特有)
启动内嵌 Web 容器
• Tomcat / Jetty / Undertow
• 注册:
• DispatcherServlet
• Filter
• Interceptor
📌 这里是 Spring Boot 和传统 Spring 最大的区别
传统 Spring:容器外有 Tomcat
Spring Boot:Tomcat 是 Bean
⸻
五、应用运行中(Running)
这时你可以:
• 接收 HTTP 请求
• 使用数据库
• 使用定时任务
• 发送 MQ 消息
典型运行期机制:
• @Scheduled
• @Async
• @EventListener
• AOP 切面
⸻
六、关闭阶段(Shutdown)
触发方式:
• JVM 关闭
• Ctrl + C
• 容器 stop
生命周期顺序:
-
发布 ContextClosedEvent
-
执行:
• @PreDestroy
• DisposableBean.destroy()
• destroy-method
-
关闭线程池、连接池
-
停止 Web 服务器
⸻
七、超重要:你真正该记住的 3 条线
① Bean 生命周期(面试 & 实战)
构造方法
→ 注入依赖
→ @PostConstruct
→ 初始化完成
→ 使用
→ @PreDestroy
⸻
② Spring Boot vs Spring
项目 Spring Spring Boot
启动方式 XML / 外部容器 main 方法
Web 服务器 外部 内嵌
自动配置 少 非常多
生命周期 一样 多了 Web 启动
⸻
③ 你写代码时该放在哪?
需求 正确位置
启动就执行 CommandLineRunner
Bean 初始化逻辑 @PostConstruct
修改 Bean 定义 BeanFactoryPostProcessor
拦截 Bean 创建 BeanPostProcessor
程序退出清理 @PreDestroy
你这个问题问得非常到位,而且不是"怎么用 Spring",而是在问它背后的概念根。我直接按你这个问题拆开说。
⸻
一、先给结论(非常重要)
在 Spring Boot 中,Bean 在启动之前「并不存在」
启动前存在的不是 Bean,而是 Bean 的"描述信息"。
换句话说:
Bean = 运行期对象
BeanDefinition = 设计图 / 蓝图 / 说明书
⸻
二、那"之前就有"的到底是什么?
不是 Bean
而是:BeanDefinition
Spring 启动时先收集一堆:
"未来要创建哪些对象"
"这些对象怎么 new"
"它们依赖谁"
"什么时候创建"
这就是 BeanDefinition
⸻
三、用英语概念精确对应(这是关键)
Spring 这套设计,对应的是几个非常标准的英语 / CS 概念:
⸻
1️⃣ Bean 本身是什么?
👉 Managed Object
• 普通 Java 对象:POJO
• 被容器托管:Managed Object
Bean = Object under IoC Container management
⸻
2️⃣ BeanDefinition 是什么?
👉 Metadata(元数据)
Spring 里的官方说法就是:
BeanDefinition = Metadata that describes a Bean
对应英语里的概念:
中文 英语
描述数据的数据 Metadata
对象说明书 Object Descriptor
构建规则 Configuration Model
📌 所以:
启动前"有"的是 metadata,不是 object
⸻
3️⃣ 为什么不是"类"?
你可能会下意识想:
"类不是早就编译好了吗?"
对,但:
• Class ≠ Bean
• Class 是 JVM 概念
• Bean 是 容器运行期概念
Spring 干的事是:
Class
→ 解析注解
→ 生成 BeanDefinition
→ 运行期 new 对象
→ 托管生命周期
⸻
四、类、BeanDefinition、Bean 的关系(非常重要)
.java 文件
↓(编译)
.class
↓(Spring 解析)
BeanDefinition ← 启动时存在
↓(refresh 阶段)
Bean(Object) ← 运行时存在
⸻
五、为什么要"先有定义,再有实例"?
这是一个非常经典的软件工程思想:
👉 Two-phase construction(两阶段构建)
英语里非常标准的概念:
Build plan first, build objects later
优点:
-
可以改"计划"(PostProcessor)
-
可以延迟创建(lazy)
-
可以做代理(AOP)
-
可以解决循环依赖
-
可以统一管理生命周期
⸻
六、类比你熟悉的东西(更好理解)
1️⃣ 数据库类比(你一定秒懂)
Spring 数据库
BeanDefinition 表结构
Bean 表中的一行数据
BeanFactory DB 引擎
⸻
2️⃣ Python / Flask 类比
@app.route("/user")
def user():
...
• 装饰器阶段:只是注册规则
• 请求进来:才真正执行函数
👉 注册 ≠ 执行
👉 Definition ≠ Instance
⸻
七、那 Bean 是不是"凭空出现的"?
不是。
Bean 是 IoC Container 根据 BeanDefinition 在运行期 new 出来的对象
Object bean = createBean(beanDefinition);
⸻
八、为什么叫 Bean?英语里原本是什么意思?
这个也很有意思。
Bean 的原始含义:
• 豆子
• 小而独立的单元
• 可组合、可管理的组件
在 Java 世界里:
• JavaBean(1990s)
• 指符合规范的小组件
Spring 继承了这个词,但升级了含义:
JavaBean + IoC 管理 + 生命周期
⸻
九、一句话终极总结(给你一个"定锚")
Spring Boot 中,Bean 不是"之前就有"的东西
之前存在的是 Bean 的元数据(BeanDefinition)
Bean 是容器 refresh 过程中按定义创建出来的运行期对象
⸻
如果你愿意,我可以下一步直接帮你把:
• BeanDefinition 的字段逐个拆开
• 或者对比 C++ 对象模型 / Python 装饰器 / JVM ClassLoader
• 或者回答你一个更底层的问题:
👉 "如果没有 IoC,Bean 这个概念还存在吗?"
你现在更想往语言层、容器层还是哲学层继续挖?