Bean的作用域和生命周期

Bean的作用域和生命周期

  • 🔎前置
    • 引入 Lombok 相关依赖
    • 下载 Lombok 插件
  • 🔎Bean的6种作用域
    • 对Bean作用域的解释
    • singleton — 单例作用域
    • prototype — 原型作用域
    • request — 请求作用域
    • session — 会话作用域
    • application — 全局作用域
    • websocket — HTTP WebSocket 作用域
    • 对比单例作用域与全局作用域
    • 设置作用域
  • 🔎Spring的执行流程
  • 🔎Bean的生命周期
    • 对Bean的生命周期的解释
    • 示例
  • 🔎结尾

🔎前置


引入 Lombok

  1. 引入 Lombok 相关依赖
  2. 下载 Lombok 插件

利用 Lombok 的注解可自动添加所需的方法

例如

  • @Getter 自动添加 getter 方法
  • @Setter 自动添加 setter 方法
  • @ToString 自动添加 toString 方法
  • @Data 包含上述的所有方法

在这里插入图片描述

引入 Lombok 相关依赖


复制如下代码至pom.xml

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version><scope>provided</scope></dependency>

在这里插入图片描述

下载 Lombok 插件


如果未找到, 可能的原因是已经下载好了(点击 Installed 查看是否下载)

在这里插入图片描述

🔎Bean的6种作用域


什么是作用域?

举个栗子🌰

定义一个成员变量, 该变量的调用范围是整个类(该成员变量的作用域)
定义一个局部变量. 该变量的调用范围是在定义该局部变量的方法内(该局部变量的作用域)

Spring 容器在初始化 Bean 实例时, 同时会指定该实例的作用域

  • singleton, 单例作用域
  • prototype, 原型作用域
  • request, 请求作用域
  • session, 会话作用域
  • application, 全局作用域
  • websocket, HTTP WebSocket 作用域

(前4种较为常见)

Bean 的作用域是指 Bean 在整个 Spring 框架中的某种行为模式
(例如 singleton — 单例作用域, 表示 Bean 在整个 Spring 中只有一份, 是全局共享的, 类似于成员变量)

对Bean作用域的解释


定义 User 类

包含 2 个属性
age — 年龄
name — 名称

在这里插入图片描述

定义 UserBeans 类

User user = new User()
设置 user.age 为 18
设置 user.name 为 bibubibu

在这里插入图片描述

定义 UserController 类

利用属性注入获取 user
将 user 赋值给 u(User u = user)
设置 u.name = Homo

在这里插入图片描述

定义 UserAdviceController 类

利用属性注入获取 user
打印此时的 user

在这里插入图片描述

运行结果

在这里插入图片描述

结果分析🍂

对于 UserController 类, 利用属性注入获取 user
对于 UserAdviceController 类, 利用属性注入获取 user
分属于不同的类, 但为何在 UserController 类中设置 u.name = Homo, 却在 UserAdviceController 类中获取到的 user 为 Homo 而不是 bibubibu?

因为 Bean 的作用域为全局共享
Bean 默认的作用域为 singleton — 单例作用域(全局共享), 因此修改 u.name 时 user.name 也被一并修改

singleton — 单例作用域


描述🍭

该作用域下的 Bean 在 IOC 容器中只存在一个实例
即获取 Bean(ApplicationContext.getBean())与装配 Bean(@Autowired)都是针对同一个对象
(Bean 的默认作用域为 singleton — 单例作用域)

适用场景🍭

通常无状态的 Bean 使用该作用域
即不会对 Bean 进行修改(只读)

为什么 Spring 选择 singleton 作为 Bean 的默认作用域🍭

单例模式只在第一次加载时速度较慢
在后续使用时可直接使用, 无需等待
因此其性能最优

prototype — 原型作用域


prototype 也可以称为多例作用域(对比单例作用域)

描述🍭

每次对该作用域下的 Bean 的请求都会创建一个新的实例(深拷贝)
即获取 Bean(ApplicationContext.getBean())与装配 Bean(@Autowired)都是针对新的对象实例

适用场景🍭

通常有状态的 Bean 使用该作用域
即会对 Bean 进行修改

request — 请求作用域


描述🍭

每次 HTTP 请求都会创建一个新的实例
一次 HTTP 的请求和响应共享同一个 Bean

适用场景🍭

在 SpringMVC 中使用

session — 会话作用域


描述🍭

在一个 HTTP Session 中创建一个新的实例

举个栗子🌰

用户 Jack 登录他的账号, 在 Jack 登陆状态中, Bean 处于共享状态(针对于 Jack 的信息)
另一个用户 Tom 登录他的账号, 在 Tom 登陆状态中, Bean 处于共享状态(针对于 Tom 的信息)
对于 Jack 和 Tom, 他们的 Bean 是隔离而非共享

适用场景🍭

在 SpringMVC 中使用

application — 全局作用域


描述🍭

在一个 HTTP Servlet Context 中创建一个新的实例

适用场景🍭

在 SpringMVC 中使用

websocket — HTTP WebSocket 作用域


描述🍭

在一个 HTTP WebSocket 的生命周期中创建一个新的实例

WebSocket 的每次会话中, 保存了一个 Map 结构的头信息, 用于包裹客户端消息头
第一次初始化后, 直到 WebSocket 结束都是同一个 Bean

适用场景🍭

在 SpringMVC 中使用

对比单例作用域与全局作用域


  1. singleton 是 Spring Core 的作用域
    application 是 Spring Web 的作用域
  2. singleton 作用于 IOC 容器
    application 作用于 Servlet 容器

设置作用域


利用 @Scope() 设置作用域

作用域设置方式
singleton — 单例作用域@Scope("singleton") / @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON))
prototype — 原型作用域@Scope("prototype") / @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
request — 请求作用域@Scope("request") / @Scope(WebApplicationContext.SCOPE_REQUEST)
session — 会话作用域@Scope("session") / @Scope(WebApplicationContext.SCOPE_SESSION)
application — 全局作用域@Scope("application") / @Scope(WebApplicationContext.SCOPE_APPLICATION)

prototype — 原型作用域 为例

在这里插入图片描述

在这里插入图片描述

🔎Spring的执行流程


  1. 启动容器(项目)
  2. 读取xml配置文件, 将 Bean 初始化
    • 直接注册 Bean(<bean id="" class=""></bean>)
    • 配置根扫描路径(<content:component-scan base-package=""></content:component-scan>)
  3. 将 Bean 存储至 Spring
  4. 从 Spring 中读取 Bean

在这里插入图片描述

启动容器(项目)

在这里插入图片描述

读取xml配置文件, 将 Bean 初始化

在这里插入图片描述

将 Bean 存储至 Spring

在这里插入图片描述

从 Spring 中读取 Bean

在这里插入图片描述

🔎Bean的生命周期


Bean 的生命周期分为 5 个部分

  1. 实例化 Bean(为 Bean 分配内存空间)
    实例化是一个从无到有的过程, 将字节码转换成内存中的对象, 分配了内存空间 → 类似于 JVM 的加载过程

  2. 设置属性(Bean 注入)

  3. 初始化 Bean

    • 实现了各种 Aware 的通知方法, 例如 BeanNameAware, BeanFactoryAware…
    • 执行 BeanPostProcessor 初始化的前置方法
    • 执行 @PostConstruct 初始化方法
    • 执行指定的 init-method 初始化方法(如果有)
    • 执行 BeanPostProcessor 初始化的后置方法
  4. 使用 Bean

  5. 销毁 Bean

对比 @PostConstruct 与 init-method

相同🍭

都是初始化方法

不同🍭

@PostConstruct 使用注解进行初始化
init-method 使用 xml 进行初始化(<bean></bean>)

执行顺序 @PostConstruct > init-method

对Bean的生命周期的解释


实例化🍂

类似于购买了一套毛坯房

设置属性(Bean 注入)🍂

为毛坯房挑选装修风格, 装修材料(引入外部资源)

Bean 初始化🍂

装修毛坯房

  • 实现了各种 Aware 的通知方法🍂
    雇用各种装修工人进行装修(水工, 电工, 瓦工…)

  • 执行 BeanPostProcessor 初始化的前置方法🍂
    装修工人到达施工现场, 制定装修方案

  • 执行初始化方法🍂
    有 2 批装修工人
    一批使用现代化装修工具但经验不足(@PostConstruct)
    另一批使用传统装修工具但经验充足(init-method)
    注解的出现时间对比xml较晚
    优先雇用使用现代化装修工具但经验不足的工人 → 执行顺序 @PostConstruct > init-method

  • 执行 BeanPostProcessor 初始化的后置方法🍂
    完成装修任务的工人做的一些善后工作(清理装修的垃圾…)

使用Bean🍂

购房者搬进装修好的房子

销毁Bean🍂

购房者将房子卖掉

示例


在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

示例代码🍂

package com.demo.component;import org.springframework.beans.factory.BeanNameAware;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;//@Component
public class BeanLifeComponent implements BeanNameAware {@Overridepublic void setBeanName(String s) {System.out.println("执行了通知");}public void init() {System.out.println("执行了 Init-method");}@PostConstructpublic void postConstruct() {System.out.println("执行了 @PostConstruct");}@PreDestroypublic void preDestroy() {System.out.println("执行 PreDestroy — 销毁方法");}
}

配置文件🍂

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:content="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><content:component-scan base-package="com.demo"></content:component-scan><bean id="myComponent" class="com.demo.component.BeanLifeComponent"init-method="init"></bean>
</beans>

示例代码🍂

public static void main(String[] args) {// ClassPathXmlApplicationContext 包含销毁方法// ApplicationContext 不包含销毁方法ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");BeanLifeComponent lifeComponent = context.getBean("myComponent", BeanLifeComponent.class);System.out.println("使用 Bean");// 销毁 Beancontext.destroy();
}

🔎结尾

创作不易,如果对您有帮助,希望您能点个免费的赞👍
大家有什么不太理解的,可以私信或者评论区留言,一起加油

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/4644.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

selenium元素定位---ElementClickInterceptedException(元素点击交互异常)解决方法

目录 前言&#xff1a; 1、异常原因 2、解决方法&#xff1a; 前言&#xff1a; 当使用Selenium进行元素定位和交互时&#xff0c;可能会遇到ElementClickInterceptedException&#xff08;元素点击交互异常&#xff09;的异常。这通常是由于页面上存在其他元素或弹出窗口遮…

MySql进阶篇(附面试快速答法)

文章目录 1、慢查询1.1、如何定位慢查询呢&#xff1f;小总结面试快速答法 1.2、SQL语句执行很慢, 如何分析呢&#xff1f;小总结面试快速答法 2、存储引擎2.1、MySQL体系结构2.2、存储引擎特点小总结 3、索引3.1、什么是索引&#xff1f;小总结面试快速答法 3.2、聚集索引和非…

GO 多线程工具使用和分析

GO 多线程工具使用和分析 Go 语言中的 sync 包提供了一些用于同步和互斥访问共享资源的原语&#xff0c;使用这些可以避免多个goroutine同时访问共享资源时出现的问题&#xff0c;他们有&#xff1a; 互斥锁读写锁condWaitGroupmaponcepoolatomic 本文介绍它们的使用方式 互…

Linux常用命令——findfs命令

在线Linux命令查询工具 findfs 标签或UUID查找文件系统 补充说明 findfs命令依据卷标&#xff08;Label&#xff09;和UUID查找文件系统所对应的设备文件。findfs命令会搜索整个磁盘&#xff0c;看是否有匹配的标签或者UUID没有&#xff0c;如果有则打印到标注输出上。find…

【Opencv】PIL Opencv 向图片写入文字并旋转文字,Opencv图片旋转不截断,Opencv图片旋转不裁剪

文章目录 失真Pillow的实现Opencv的实现不裁剪的旋转图像旋转文字并贴图C的图片透视变换 失真 刚性变换&#xff1a; 只有物体的位置(平移变换)和朝向(旋转变换)发生改变&#xff0c;而形状不变&#xff0c;得到的变换称为刚性变换。刚性变换是最一般的变换。 使用透视变换&a…

基于matlab多运动目标跟踪监测算法实现(附源码)

一、前言 此示例演示如何对来自固定摄像机的视频中的移动对象执行自动检测和基于运动的跟踪。 二、介绍 移动物体检测和基于运动的跟踪是许多计算机视觉应用的重要组成部分&#xff0c;包括活动识别、交通监控和汽车安全。基于运动的对象跟踪问题可以分为两部分&#xff1a; 检…

【人工智能与机器学习】决策树ID3及其python实现

文章目录 1 决策树算法1.1 特征选择1.2 熵&#xff08;entropy&#xff09;1.3 信息增益 2 ID3算法的python实现总结 1 决策树算法 决策树&#xff08;Decision Tree)是一类常见的机器学习方法&#xff0c;是一种非常常用的分类方法&#xff0c;它是一种监督学习。常见的决策树…

ChatGPT实战:高考志愿填报

近期&#xff0c;随着各地陆续发布高考成绩&#xff0c;高考志愿填报市场随之升温&#xff0c;“高报师”再次成为“香饽饽”。填报志愿对中学生来说太难&#xff0c;在一个懵懂的年纪做这样一个决策&#xff0c;份量是比较重的。当普通人没很多的信息做参考的时候&#xff0c;…

LeetCode 剑指 Offer 13. 机器人的运动范围(深度遍历)

LeetCode 剑指 Offer 13. 机器人的运动范围 原题思路代码运行截图收获 原题 LeetCode 剑指 Offer 13. 机器人的运动范围 思路 通过深度遍历来找出所有可达的格子通过0、1、2来区分未遍历、可到达、不可到达三种状态 代码 class Solution { public:int visited[109][109];i…

python中使用OAK-D PRO相机实现OCR功能

目录 OAK简介Tesseract简介Tesseract OCR安装包安装 Tesseract OCR 代码实现 OAK简介 OAK&#xff08;OpenCV AI Kit&#xff09;是一个开源的智能视觉平台&#xff0c;它集成了硬件和软件组件&#xff0c;旨在提供高性能的实时目标检测、识别和跟踪等视觉AI功能。OAK由Luxoni…

【机器学习】信息熵和信息度量

一、说明 信息熵是概率论在信息论的应用,它简洁完整,比统计方法更具有计算优势。在机器学习中经常用到信息熵概念,比如决策树、逻辑回归、EM算法等。本文初略介绍一个皮毛,更多细节等展开继续讨论。 二、关于信息熵的概念 2.1 要素描述 信息熵:熵是一种测量随机变量 X …

CVE-2023-34541 LangChain 任意命令执行

漏洞简介 LangChain是一个用于开发由语言模型驱动的应用程序的框架。 在LangChain受影响版本中&#xff0c;由于load_prompt函数加载提示文件时未对加载内容进行安全过滤&#xff0c;攻击者可通过构造包含恶意命令的提示文件&#xff0c;诱导用户加载该文件&#xff0c;即可造…