当前位置: 首页 > news >正文

bean的作用域与生命周期

一、Bean的作用域

1.1 什么是Bean作用域?

简单来说,Bean作用域是Spring用来控制Bean实例创建数量、对象存活范围的核心机制。

一句话区分:从Spring容器中取Bean,是一直用同一个对象,还是每次都新建对象,全部由作用域决定

Spring内置一共6种作用域,分为:4种通用作用域 + 2种Web专属作用域。通用作用域可用于所有Spring项目,Web专属作用域仅适用于Web工程。

1.2 六大作用域详细汇总

作用域类型

核心含义

实例数量

适用场景

singleton(默认)

单例作用域,整个Spring容器全局仅存在一个Bean实例

全局1个

无状态Bean,日常开发绝大多数场景:Service、Controller、Dao、工具类

prototype

原型多例作用域,每次获取、注入Bean都会新建对象

多个

有状态Bean、需要独立对象、避免数据共享冲突的场景

request

一次HTTP请求对应一个独立Bean实例

请求级

Web项目,存储单次请求的临时数据

session

一个用户会话对应一个Bean实例

会话级

存储用户登录状态、会话缓存数据

application

整个Web应用全局唯一,和项目容器同生命周期

全局1个

项目全局配置、公共常量、全局参数

websocket

一个WebSocket长连接对应一个Bean实例

连接级

即时通讯、消息推送、WebSocket长连接业务

1.3 核心作用域代码实战(开发常用)

实际开发中,我们使用最多的只有singleton(单例)prototype(多例),其余Web专属作用域仅在特殊业务场景中使用。

1、singleton 单例(默认作用域)

Spring容器启动初始化阶段就会创建单例Bean,全局共享同一个对象,程序中所有注入、获取Bean的操作,拿到的都是同一个实例。

核心特点:容器启动初始化、全局唯一、性能高、非线程安全

2、prototype 多例(原型作用域)

多例Bean不会在容器启动时初始化,每次注入、调用getBean()获取Bean时,都会全新创建一个对象

核心特点:多实例、线程安全、Spring不管理多例Bean的初始化和销毁生命周期


二、Bean完整生命周期

Bean生命周期,就是Bean在Spring IoC容器中从创建、赋值、初始化、使用到最终销毁的完整全过程。

这是Java后端面试高频必考知识点,同时也是解决Spring Bean注入报错、初始化异常、对象失效等问题的核心底层依据!

2.1 整体执行流程

容器启动 → 实例化 → 属性赋值 → Aware回调 → 前置处理器 → 初始化 → 后置处理器 → 就绪使用 → 容器关闭销毁

2.2 七步流程详细拆解

第一步:实例化(new空对象)

Spring IoC容器启动后,通过反射机制调用类的无参构造方法,为Bean创建一个空对象,完成实例化操作。

💡 重点:自定义Bean类如果没有无参构造方法,会直接抛出异常,导致Bean创建失败!

第二步:属性赋值(依赖注入)

容器通过setter方法、构造器注入、@Autowired注解等多种方式,为实例化后的空对象完成成员变量赋值,实现依赖注入。

💡 日常开发中常见的“找不到setter方法”“依赖注入失败”报错,基本都出在这一步。

第三步:Aware接口容器回调

Spring提供内置扩展接口,让Bean具备感知Spring容器资源的能力,完成容器资源的绑定:

  • BeanNameAware:获取当前Bean的名称/id

  • BeanFactoryAware:获取当前Bean工厂对象

  • ApplicationContextAware:获取Spring全局上下文对象

第四步:Bean前后置处理器增强

BeanPostProcessor(Bean后置处理器)是Spring的全局核心增强机制,也是Spring AOP、注解功能增强的底层原理。会在Bean初始化前后,执行自定义的前置、后置处理逻辑。

第五步:自定义初始化逻辑

Spring提供三种自定义Bean初始化逻辑的方式,执行优先级从高到低

  1. @PostConstruct 注解(开发推荐,简洁高效)

  2. 实现InitializingBean接口

  3. XML配置 init-method 属性

第六步:Bean就绪使用

所有初始化流程执行完毕后,完整的Bean对象会被存入Spring单例池,正式就绪,对外提供业务调用服务。

第七步:容器关闭销毁

仅单例Bean会被Spring容器管理销毁,多例Bean由JVM垃圾回收管理。Spring提供两种销毁逻辑实现方式:

  • @PreDestroy 注解

  • 实现DisposableBean接口

2.3 完整生命周期代码演示

以下代码可直接复制运行,控制台会精准打印每一步的执行顺序,直观看懂Bean完整生命周期:

import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.DisposableBean; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; /** * Spring Bean 完整生命周期测试 * @author 个人博客 */ public class LifeCycleBean implements BeanNameAware, InitializingBean, DisposableBean { // 1. 实例化:执行无参构造创建空对象 public LifeCycleBean() { System.out.println("1、Bean实例化:执行无参构造"); } // 3. Aware接口回调:获取Bean名称 @Override public void setBeanName(String name) { System.out.println("3、Aware接口回调:Bean名称 = " + name); } // 4. 注解初始化(优先级最高) @PostConstruct public void postConstruct() { System.out.println("5、初始化:@PostConstruct 执行"); } // 5. 接口初始化 @Override public void afterPropertiesSet() throws Exception { System.out.println("5、初始化:InitializingBean 执行"); } // 销毁方法1:注解销毁 @PreDestroy public void preDestroy() { System.out.println("7、销毁:@PreDestroy 执行"); } // 销毁方法2:接口销毁 @Override public void destroy() throws Exception { System.out.println("7、销毁:DisposableBean 执行"); } }

2.4 生命周期最终执行顺序

无参构造实例化 → 属性赋值 → Aware接口回调 → Bean前置处理器 → @PostConstruct → InitializingBean → init-method → Bean后置处理器 → Bean使用阶段 → 容器关闭销毁


三、作用域与生命周期关联关系

很多同学会混淆两者的关联,这里做精准总结,区分不同作用域Bean的生命周期差异:

  • singleton单例Bean:容器启动时完成实例化、赋值、全部初始化流程,容器关闭时触发销毁,完整生命周期全程由Spring IoC容器管理

  • prototype多例Bean:仅在调用获取时创建对象,Spring只负责实例化和属性赋值,不管理初始化、销毁流程,对象生命周期由JVM全权管理

  • Web专属作用域Bean(request/session/application/websocket):生命周期跟随HTTP请求、用户会话、WebSocket长连接,一旦请求结束、会话过期、连接断开,Bean自动销毁


四、全文总结

1、Bean作用域的核心作用是控制Bean的实例数量和存活范围,日常开发99%场景仅使用单例、多例两种作用域;

2、单例Bean性能优异但非线程安全,适合无状态业务;多例Bean线程安全但创建开销更大,适合有状态业务;

3、Bean完整生命周期是Spring IoC的核心底层逻辑,熟记七步执行流程,可解决绝大多数Bean注入、初始化、报错问题;

4、Spring容器只全权管理单例Bean的完整生命周期,多例Bean仅负责创建赋值,不负责后续生命周期管理。

http://www.cnnetsun.cn/news/2627069.html

相关文章:

  • 6Pin数码管驱动和编码器旋钮检测
  • 从Solidworks草图到桌面摆件:我如何用3D打印给自己做了个PLA手机支架(附切片避坑指南)
  • Taotoken用量看板与成本管理功能的实际使用观感
  • 基于ESP32与SCD41传感器的开源智能CO₂监测仪制作全攻略
  • 如何用哔哩下载姬downkyi轻松下载B站视频:从入门到精通完全指南
  • WingData HTB 渗透测试完整攻略
  • 别再自己写扫码了!用uniapp插件Ba-Scanner,5分钟搞定连续扫码和自定义UI
  • 笔记本刚开机就高温?CPU 90℃、风扇狂转、网速消耗殆尽——威胁检测工程师实战排查全过程
  • PointPillars算法避坑指南:从VoxelNet到Apollo实战,聊聊那些容易踩的‘坑’
  • 权重衰减为何放入优化器
  • 什么是OPC(一人公司)?
  • 代码即玩法:非典型游戏开发的英文提示词实践
  • 从 MCP 到 A2A:Agent 项目里“通信协议”到底在解决什么问题?
  • 别再手动排路线了!用Python+遗传算法搞定物流配送VRP(附完整代码)
  • 番茄小说下载器完整指南:打造个人离线数字图书馆的终极方案
  • 2026权威实测:16款降AIGC软件横评,论文安全过关就靠它!
  • 如何用Ai2Psd脚本实现Illustrator到Photoshop的无损图层转换?3步极速指南
  • 真机实测:Hermes Agent Windows 全流程安装与配置指南
  • 多活不是口号,是算力——DeepSeek高可用架构落地三原则,含真实RTT压测数据与Failover耗时对比表
  • RPGMakerDecrypter完全指南:3步解密RPG Maker加密存档的专业方法
  • LAMMPS模拟石墨烯拉伸:除了velocity,试试这个更省事的deform命令(附完整in文件)
  • 告别公式恐惧!用Python一步步拆解LTE PUCCH功率控制(附代码与实战日志分析)
  • Nintendo Switch文件管理难题?NX-Shell为你提供终极解决方案
  • 论企业网络设计
  • 如何用5个步骤快速掌握哔哩下载姬DownKyi:B站视频下载终极方案
  • 嵌入式Linux内存稳定性测试:手把手教你用memtester排查硬件‘暗病’(附RK3399实测)
  • 构建智能知识图谱维基:从NLP到图数据库的工程实践
  • DDrawCompat完整指南:5分钟让经典Windows游戏在现代系统重生
  • Mac窗口管理新思路:除了Magnet分屏,试试AfloatX的“悬浮”与“沉底”魔法
  • Taotoken 助力游戏服务器实现智能 NPC 对话与剧情生成