Spring Bean 作用域 & 生命周期 超详细易懂笔记(零基础可学)
哈喽!这篇笔记专门整理 Spring 中 Bean 作用域 和 Bean 生命周期 核心知识点,全程通俗易懂、无废话,适合背诵、面试复习、日常查漏补缺,零基础也能看懂。
先铺垫一句核心:Spring 容器的核心就是管理 Bean,搞懂 Bean 的"存活范围(作用域)"和"一生流程(生命周期)",就吃透了 Spring 基础大半壁江山。
一、什么是 Bean?(前置理解)
在 Spring 中,Bean 就是由 Spring IoC 容器创建、管理、赋值、销毁的 Java 对象。
我们自己 new 的对象,不受 Spring 管理;
交给 Spring 托管的对象,统一叫 Bean。
Spring 对 Bean 的管控主要两件事:
- 作用域:这个 Bean 能活多久、全局有几个实例
- 生命周期:这个 Bean 从创建到销毁的完整执行流程
二、Bean 的 6 大作用域(重点!面试必考)
2.1 作用域核心概念
Bean 作用域 :定义 Spring 容器中 Bean 实例的数量 和 存活的有效范围。
Spring 官方提供 6 种作用域,其中 2 个常用核心作用域,4 个 Web 环境专属作用域。
2.2 六大作用域详细解析
1. singleton(单例,默认作用域)
特点:
- 整个 Spring IoC 容器中只会存在一个 Bean 实例
- 全局共享,所有请求、所有线程共用这一个对象
- 默认作用域(不指定 scope 就是 singleton)
创建时机:
- 默认:容器启动时立即创建(饿汉式)
- 加
@Lazy:首次使用时创建(懒汉式)
适用场景:无状态对象(Controller、Service、Dao、工具类)
注意坑 :单例 Bean 非线程安全,不要在 Bean 中定义成员变量存储请求数据,会出现数据错乱!
2. prototype(多例)
特点:
- 每次从容器中获取 Bean / 注入 Bean,都会创建一个全新的实例
- 容器启动时不会创建,用一次、建一次
- 容器只负责创建,不负责 prototype Bean 的销毁(垃圾回收由 JVM 管理)
适用场景:有状态对象、需要独立实例的对象(保存用户私有数据、临时对象)
3. request(Web 专属)
一次 HTTP 请求 对应一个 Bean 实例,请求结束,Bean 销毁。
4. session(Web 专属)
一个 用户会话 Session 对应一个 Bean 实例,会话过期/关闭,Bean 销毁。
5. application(Web 专属)
对应 整个 Web 应用,作用域等同于 ServletContext,全局唯一,和容器同生共死。
6. websocket(Web 专属)
一个 WebSocket 连接对应一个 Bean,连接断开则 Bean 销毁。
2.3 作用域快速总结表(记忆神器)
| 作用域 | 实例数量 | 创建时机 | 适用场景 |
|---|---|---|---|
| singleton | 全局1个 | 容器启动(默认) | 无状态全局组件(默认) |
| prototype | 每次获取1个新的 | 每次使用时 | 有状态、独立对象 |
| request | 单次请求1个 | 请求到来 | 请求级临时数据 |
| session | 单个会话1个 | 会话创建 | 用户会话数据 |
2.4 作用域注解使用方式
java
// 默认单例
@Scope("singleton")
// 多例
@Scope("prototype")
// Web作用域同理
@Scope("request")
三、Bean 的完整生命周期(超清晰流程)
Bean 生命周期 :Spring Bean 从 实例创建 → 属性赋值 → 初始化 → 就绪使用 → 容器关闭销毁 的全过程。
整个流程分为 5 大核心阶段,我按执行顺序一步步拆解,附带每一步的作用。
3.1 完整生命周期执行顺序(背诵版)
1. 实例化(new 对象)→ 2. 属性填充(依赖注入)→ 3. 初始化前置处理 → 4. 初始化 → 5. 销毁
3.2 逐阶段详细讲解
阶段1:Bean 实例化
Spring 读取配置类/XML,扫描到 Bean 注解,通过反射调用无参构造器创建对象。
此时:对象是空的,属性还没有赋值。
阶段2:属性填充(依赖注入 DI)
Spring 自动完成 属性赋值、自动装配(@Autowired、@Resource),把依赖的 Bean 注入进来。
此时:对象的属性已经赋值完成,但还没有执行初始化方法。
阶段3:Bean 后置处理器前置处理(BeanPostProcessor)
Spring 提供的扩展点,在初始化之前对 Bean 做增强、修改、包装。
经典场景:AOP 代理就是在这里完成的!
阶段4:Bean 初始化(核心)
初始化内部又分为 4 个小步骤,顺序固定:
- 执行 Aware 接口方法
如果 Bean 实现了 Spring 内置的 Aware 接口,会先执行对应方法,让 Bean 感知 Spring 容器资源:
- BeanNameAware:获取当前 Bean 名称
- BeanFactoryAware:获取 Bean 工厂
- ApplicationContextAware:获取 Spring 上下文
-
执行 @PostConstruct 注解方法
JSR250 规范注解,属性注入完成后执行,用于初始化资源、加载数据。
-
执行 InitializingBean 接口的 afterPropertiesSet()
Spring 内置初始化接口,优先级低于 @PostConstruct。
-
执行自定义 init-method
XML 或 @Bean 注解指定的初始化方法。
阶段5:Bean 就绪,正式使用
初始化完成后,Bean 正式存入单例池,对外提供服务,接收请求、执行业务逻辑。
阶段6:Bean 销毁
当 Spring 容器关闭(close)时,会执行销毁方法,仅针对 singleton 单例 Bean 生效!
销毁执行顺序:
- @PreDestroy 注解方法
- DisposableBean 接口 destroy() 方法
- 自定义 destroy-method
重点结论 :
prototype 多例 Bean 容器不负责销毁,只有单例 Bean 会被容器统一销毁!
3.3 初始化方法优先级(面试高频)
优先级从高到低:
@PostConstruct > InitializingBean > 自定义 init-method
3.4 完整生命周期流程图(文字版,超好记)
容器启动 → 扫描Bean → 反射实例化 → DI依赖注入 → BeanPostProcessor前置处理 → Aware接口 → @PostConstruct → InitializingBean → init-method → Bean可用 → 容器关闭 → @PreDestroy → DisposableBean → destroy-method
四、重难点 & 面试高频问答(必背)
Q1:singleton 和 prototype 最大区别?
- singleton:全局单例,容器启动创建,容器负责销毁,非线程安全
- prototype:多实例,使用时创建,容器不销毁,线程独立安全
Q2:为什么 Controller/Service 用单例?
因为这些组件是无状态的,不存储用户私有数据,单例可以减少对象创建开销,提升性能。
Q3:Bean 是线程安全的吗?
- singleton 单例 Bean:线程不安全(全局共享成员变量)
- prototype 多例 Bean:线程安全(每个线程独立实例)
Q4:Bean 生命周期中,AOP 代理发生在哪个阶段?
BeanPostProcessor 后置处理阶段,在初始化完成后,对原生 Bean 进行动态代理增强。
Q5:多例 Bean 会执行销毁方法吗?
不会,Spring 容器只管理单例 Bean 的销毁,多例 Bean 由 JVM GC 回收。
五、最终总结(极简背诵版)
- 作用域核心:默认单例 singleton,多用多例 prototype,Web 环境专属 request/session/application/websocket。
- 生命周期核心流程:实例化 → 依赖注入 → 后置处理 → 初始化 → 使用 → 销毁。
- 初始化优先级:注解 > 接口 > 自定义方法。
- 唯一区别:单例容器全权管理,多例只用不管、不销毁。