Spring Bean 作用域 & 生命周期

Spring Bean 作用域 & 生命周期 超详细易懂笔记(零基础可学)

哈喽!这篇笔记专门整理 Spring 中 Bean 作用域 和 Bean 生命周期 核心知识点,全程通俗易懂、无废话,适合背诵、面试复习、日常查漏补缺,零基础也能看懂。

先铺垫一句核心:Spring 容器的核心就是管理 Bean,搞懂 Bean 的"存活范围(作用域)"和"一生流程(生命周期)",就吃透了 Spring 基础大半壁江山。


一、什么是 Bean?(前置理解)

在 Spring 中,Bean 就是由 Spring IoC 容器创建、管理、赋值、销毁的 Java 对象。

我们自己 new 的对象,不受 Spring 管理;

交给 Spring 托管的对象,统一叫 Bean。

Spring 对 Bean 的管控主要两件事:

  1. 作用域:这个 Bean 能活多久、全局有几个实例
  2. 生命周期:这个 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 个小步骤,顺序固定:

  1. 执行 Aware 接口方法
    如果 Bean 实现了 Spring 内置的 Aware 接口,会先执行对应方法,让 Bean 感知 Spring 容器资源:
  • BeanNameAware:获取当前 Bean 名称
  • BeanFactoryAware:获取 Bean 工厂
  • ApplicationContextAware:获取 Spring 上下文
  1. 执行 @PostConstruct 注解方法

    JSR250 规范注解,属性注入完成后执行,用于初始化资源、加载数据。

  2. 执行 InitializingBean 接口的 afterPropertiesSet()

    Spring 内置初始化接口,优先级低于 @PostConstruct。

  3. 执行自定义 init-method

    XML 或 @Bean 注解指定的初始化方法。

阶段5:Bean 就绪,正式使用

初始化完成后,Bean 正式存入单例池,对外提供服务,接收请求、执行业务逻辑。

阶段6:Bean 销毁

当 Spring 容器关闭(close)时,会执行销毁方法,仅针对 singleton 单例 Bean 生效!

销毁执行顺序:

  1. @PreDestroy 注解方法
  2. DisposableBean 接口 destroy() 方法
  3. 自定义 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 回收。


五、最终总结(极简背诵版)

  1. 作用域核心:默认单例 singleton,多用多例 prototype,Web 环境专属 request/session/application/websocket。
  2. 生命周期核心流程:实例化 → 依赖注入 → 后置处理 → 初始化 → 使用 → 销毁。
  3. 初始化优先级:注解 > 接口 > 自定义方法。
  4. 唯一区别:单例容器全权管理,多例只用不管、不销毁。
相关推荐
文丑颜不良啊14 分钟前
LeetCode2541~2560题目解析
java·leetcode
Anymous18 分钟前
我手写的 Redis 锁,输给了 10 秒的 TTL
后端·架构
瑞雪兆丰年兮22 分钟前
JavaWeb-day11-SpringBootWeb案例(文件上传)
java·运维·服务器·javaweb·oss
Highcharts.js1 小时前
Highcharts智能数据分析平台Orbit 多语言配置技术文档
java·前端·javascript·highcharts·orbit·智能数据分析·设置文档
Rain的Java大神之路1 小时前
设计一套生产级 API 接口:从契约、安全、幂等到限流,我踩过的坑都在这了
java·后端·面试
SimonKing1 小时前
零配置也能白嫖前沿大模型!dsh-our-free-model插件真香警告
java·后端·程序员
nice_lcj5201 小时前
【从零理解 Spring AI · 15】让检索更准:先宽召回,再精排序
java·后端·rag·spring ai·ai应用开发·检索优化·重排序
回家路上绕了弯1 小时前
要人确认的那一步,在确认什么?
后端
IT_陈寒2 小时前
JavaScript项目实战经验分享:从内存泄漏到性能优化的血泪史
前端·人工智能·后端
杨凯凡2 小时前
Spring Boot 链路追踪实战:Micrometer、TraceId 与异步线程上下文传播
java·spring boot·后端