【Spring】——Spring生命周期

前言

❤️❤️❤️Spring专栏更新中,各位大佬觉得写得不错,支持一下,感谢了!❤️❤️❤️

Spring_冷兮雪的博客-CSDN博客

前面我们讲完了Spring中有关Bean的读和取,我们还没有好好去了解了解Bean对象,这篇 就是对Bean的深入学习。

一、Bean的作用域🍭

1、理解概念🍉

限定程序中变量的可用范围叫做作用域,或者说在源代码中定义变量的某个区域就叫做作用域。而Bean 的作用域是指 Bean 在 Spring 整个框架中的某种行为模式,比如 singleton 单例作用域,就表示 Bean 在整个 Spring 中只有一份,它是全局共享的,那么当其他人修改了这个值之后,另一个人读取到的就是被修改的值。

Singleton 单例模式是一种创建型设计模式,它保证一个类只有一个实例,并提供该实例的全局访问点。

使用 Singleton 模式的主要目的是确保在一个应用程序中,某个类的对象只有一个,这样可以节省系统资源,避免对同一数据的多重处理等问题。在实现时,我们需要注意线程安全、延迟初始化、序列化和反射等方面的问题。

一般来说,Singleton 模式适用于那些需要频繁访问的对象,例如日志记录器、数据库连接池、线程池等等。

2、通过案例理解 Bean 作用域🍉

有一个公共的 Bean,提供给 A 用户和 B 用户使用,然而在使用的途中 A 用户却“悄悄”地修 改了公共 Bean 的数据,导致 B 用户在使用时发生了预期之外的逻辑错误。
公共 Bean:
@Component
public class Users {
    @Bean
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("Java"); // 【重点:名称是 Java】
        return user;
    }
}
A 用户使用时,进行了修改操作:
@Controller
public class BeanScopesController {
    @Autowired
    private User user1;

    public User getUser1() {
        User user = user1;
        System.out.println("Bean 原 Name:" + user.getName());
        user.setName("悟空"); // 【重点:进⾏了修改操作】
        return user;
    }
}
B 用户再去使用公共 Bean 的时候:
@Controller
public class BeanScopesController2 {
    @Autowired
    private User user1;

    public User getUser1() {
        User user = user1;
        return user;
    }
}
打印 A 用户和 B 用户公共 Bean 的值:
public class App {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        BeanScopesController beanScopesController = context.getBean("beanScopesController",BeanScopesController.class);
        System.out.println("A 对象修改之后 " + beanScopesController.getUser1().toString());
        BeanScopesController2 beanScopesController2 = context.getBean("beanScopesController2",BeanScopesController2.class);
        System.out.println("B 对象读取到的 " + beanScopesController2.getUser1().toString());
    }
}

运行结果:

 Ⅰ、原因分析🍓

通过上面这个案例我们发现所有人的使用的都是同 一个对象,这也验证了我们之前说的:在 Spring 中 Bean 的作用域默认是 singleton 单例模式。

3、Bean 的 6 种作用域(前四种为常用)🍉

Spring 容器在初始化⼀个 Bean 的实例时,同时会指定该实例的作用域。Spring有 6 种作用域,最后四种是基于 Spring MVC 生效的:
  1. singleton:单例作用域
  2. prototype:原型作用域(多例作用域)
  3. request:请求作用域
  4. session:回话作用域
  5. application:全局作用域
  6. websocket:HTTP WebSocket 作用域
其中前两种是 spring 核心作用域,而后 4 种是 spring mvc 中的作用域。

Ⅰ、singleton(单例模式)🍓

  • 官方说明:(默认)将单个bean定义作用于每个Spring IoC容器的单个对象实例。
  • 描述:该作用域下的Bean在IoC容器中只存在⼀个实例:获取Bean(即通过 applicationContext.getBean等方法获取)及装配Bean(即通过@Autowired注入)都是同一个对象。
  • 场景:通常无状态的Bean使用该作用域。无状态表示Bean对象的属性状态不需要更新。
  • 备注:Spring默认选择该作用域

Spring 框架默认采用 Singleton 单例模式,主要是因为以下几点原因:

  1. 资源消耗较少:使用单例模式可以避免频繁创建对象,节约系统资源,提升系统性能。

  2. 对象复用:当多个组件需要使用同一个对象时,采用单例模式可以确保这些组件使用的是同一个对象,保证了对象的一致性和正确性。

  3. 统一管理:采用单例模式可以方便地对对象进行统一管理,例如设置各种属性、初始化等操作。

  4. 易于扩展:当需要增加或修改某个类的实现时,只需要修改该类的单例实例即可,无需修改其他代码。

想了解或者复习单例模式可以看这篇文章:

 面试突击50:单例模式有几种写法? - 掘金 (juejin.cn)

 Ⅱ、prototype(原型模式/多例模式)🍓

  • 官方说明:将单个bean定义限定为任意数量的对象实例。
  • 描述:每次对该作用域下的Bean的请求都会创建新的实例:获取Bean(即通过 applicationContext.getBean等方法获取)及装配Bean(即通过@Autowired注入)都是新的对象实例。
  • 场景:通常有状态的Bean使用该作用域。有状态表示Bean对象的属性状态需要更新。

Ⅲ、request(请求作用域)🍓

  • 官方说明:将单个bean定义限定在单个HTTP请求的生命周期内。也就是说,每个HTTP请求都有自己的bean实例,该实例是在单个bean定义的后面创建的。只在具有web感知的Spring ApplicationContext上下文中有效。
  • 描述:每次http请求会创建新的Bean实例,类似于prototype。
  • 场景:一次http的请求和响应的共享Bean。
  • 备注:限定SpringMVC(Spring外部项目)中使用。

Ⅳ、session(回话作用域)🍓

  • 官方说明:将单个bean定义限定在HTTP会话的生命周期内。只在具有web感知的Spring ApplicationContext上下文中有效。
  • 描述:在一个http session中,定义⼀个Bean实例。
  • 场景:用户回话的共享Bean, 比如:记录⼀个用户的登陆信息。
  • 备注:限定SpringMVC中使用。

Ⅴ、application(全局作用域 | 了解)🍓

  • 官方说明:将单个bean定义限定在ServletContext的生命周期内。仅在支持web的Spring ApplicationContext的上下文。
  • 描述:在一个http servlet Context中,定义一个Bean实例。
  • 场景:Web应用的上下文信息,比如:记录一个应用的共享信息。
  • 备注:限定SpringMVC中使用。

Ⅵ、websocket(了解)🍓

  • 官方说明:将单个bean定义限定在WebSocket的生命周期内。仅在一个具有web感知的Spring ApplicationContext。
  • 描述:在一个HTTP WebSocket的生命周期中,定义一个Bean实例。
  • 场景:WebSocket的每次会话中,保存了一个Map结构的头信息,将用来包裹客户端消息头。第一次初始化后,直到WebSocket结束都是同一个Bean。
  • 备注:限定Spring WebSocket中使用。

单例作用域(singleton) VS 全局作用域(application)🍓

  • singleton 是 Spring Core 的作用域;application 是 Spring Web 中的作用域;
  • singleton 作用于 IoC 的容器,而 application 作用于 Servlet 容器。

 4、设置作用域🍉

设置作用域有两种方法:

Ⅰ、直接设置值:@Scope("prototype")🍓

还是前面的代码,我们给user1设置prototype作用域 (也可以设置成其他作用域)

运行:

 Ⅱ、使用全局变量设置:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)🍓

通过@Scope(ConfigurableListableBeanFactory.SCOPE_PROTOTYPE)修改作用域

 我们运行代码也可以可以得到与 前一方法 相同的结果:

 二. Spring 执行流程和 Bean 的生命周期🍭

 1、Spring 执行流程 🍉

  1. 启动容器(启动项目)。
  2. 读取配置文件,初始化。
  3. a)使用 xml 直接注册 beanb)配置 bean 根 (扫描)路径3.将 bean 存储到 spring 中,通过类注解进行扫描和装配。
  4. 将 bean 从 spring 读取出来,装配到相应的类。

2、Bean的生命周期 🍉

所谓的生命周期指的是一个对象从诞生到销毁的整个生命过程,我们把这个过程就叫做一个对象的生命周期。
Bean 的生命周期分为以下 5 大部分:
  1. 实例化:当Spring容器接收到一个Bean的定义时,会根据该定义创建一个Bean的实例。

  2. 属性赋值:创建Bean的实例后,Spring通过反射机制将Bean属性设置为相应的值。通常情况下,这些 Bean 属性的值来自于配置文件或注解等方式。

  3. 初始化:在Bean实例化并设置好所有属性之后,Spring容器将调用特定的方法对Bean进行初始化,例如执行自定义的初始化方法或BeanPostProcessor接口中的回调方法等。

  4. 使用:当Bean初始化完成后,它可以被Spring容器使用了。在此阶段,Bean可以响应容器中的请求,执行相应的业务逻辑。

  5. 销毁:当应用程序关闭或者Spring容器销毁时,会调用已注册的bean的销毁方法,以释放资源。这个销毁方法也可以是自定义的,需要实现DisposableBean接口或者添加@PreDestroy注解。

销毁容器的各种方法,如 @PreDestroy、DisposableBean 接口方法、destroy-method。
执行流程如下图所示:

多学一招: 实例化和初始化的区别

实例化和初始化是Bean生命周期中的两个不同阶段。

实例化:指根据配置文件或注解等方式,创建一个对象实例的过程。在Spring容器启动时,会根据定义的Bean定义信息创建相应的Bean实例,并将其添加到容器中进行管理。这个过程可以通过构造函数、工厂方法或者其他方式来实现。

初始化:指在Bean实例化后,进行必要的属性设置、调用接口方法以及执行自定义初始化方法等操作,使得Bean达到可以使用的状态。在Spring容器创建了Bean实例之后,会根据配置信息和需要执行一定的初始化操作,例如调用BeanPostProcessor接口中的回调方法、执行自定义的初始化方法等等。

总之,Bean的实例化和初始化是在Spring容器中管理Bean的重要环节,它们各自都有着不同的作用和实现方式。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于appnium+python+夜神模拟器的自动化

目录 1、安装夜神模拟器 2、定位元素 3、开始编码 首先搭好appnium环境!参考https://www.cnblogs.com/testlearn/p/11419797.html 1、安装夜神模拟器 下载安装夜神模拟器后,在cmd命令输入adb connect 127.0.0.1:62001,显示出设备则表示…

redis协议与异步方式学习笔记

目录 1 交互方式 pipline2 广播机制2.1 概念演示2.2 使用场景 3 redis事物3.1 概念3.2 使用场景3.3 解决的问题3.3.1 背景:多线程竞争出现问题3.3.2 事务3.3.3 安全性事务 3.4两种类型的“事务”3.4.1 watch ... multi exec3.4.2 lua 脚本实现“原子”执行&#xff…

再以汇编代码分析c++的右值引用

汇编分析c语言的执行结果最为准确。 可见,右值引用其实还是引用, bb 和 cc 都是对 aa 的引用,其内存里存储了 aa 的地址。 而且还有一个很奇特的现象,bb无法给cc赋值,右值引用无法给右值赋值。 同样是调用std:: move…

d2l_第七章学习_卷积神经网络

参考: d2l今日学习——卷积神经网络(CNN)https://blog.csdn.net/m0_61165991/article/details/124176077图像工程(上册)-图像处理傅里叶变换https://blog.csdn.net/qq_43369406/article/details/131350139CNN卷积神经网络基础知识…

STC15 Proteus仿真DHT11环境湿度采集报警系统STC15W4K32S4-0043

STC15 Proteus仿真DHT11环境湿度采集报警系统STC15W4K32S4-0043 Proteus仿真小实验: STM32 Proteus仿真DHT11环境湿度采集报警系统STC15W4K32S4-0043 功能: Protues版本:8.9 硬件组成:STC15W4K32S4单片机 LCD1602显示器DHT11…

基于深度学习的高精度推土机检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要:基于深度学习的高精度推土机检测识别系统可用于日常生活中检测与定位推土机目标,利用深度学习算法可实现图片、视频、摄像头等方式的推土机目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训…

2023 node 接入腾讯云短信服务,实现发送短信功能

1、在 腾讯云开通短信服务,并申请签名和正文模板 腾讯云短信 https://console.cloud.tencent.com/smsv2 a、签名即是短信的开头。例如 【腾讯云短信】xxxxxxx; b、正文模板即短信内容, 变量部分使用{1}, 数字从1开始累推。例如&a…

深度学习-第T10周——数据增强

深度学习-第T10周——数据增强 深度学习-第T10周——数据增强一、前言二、我的环境三、前期工作1、导入数据集2、查看图片数目 四、数据预处理1、 加载数据1.1、设置图片格式1.2、划分训练集1.3、划分验证集1.4、查看标签1.5、再次检查数据1.6、配置数据集 2、数据可视化 五、数…

软件工程实践总结

前言 这次我们学校花了很多心血在这次的课设上,真的是特别感动和感谢,当你遇到真心为你好对你好的老师的时候,真的是会觉得人间值得! 之前在学软件工程的时候我就会觉得这些理论的东西有什么用啊,什么UML,…

Scrapy框架之下载中间件(详解)

目录 Scrapy中下载中间件 概念 方法 process_request(self, request, spider) 参数: process_response(self, request, response, spider) 参数 基本步骤 示例代码 注意 Scrapy 中 Downloader 设置UA 开发UserAgent下载中间件 代码 三方模块 配置模块到Settin…

【js30天挑战】第四天:数组操作

总结 filter(筛选条件为true的项) map(你想要输出的东西),进来多少个 出去多少个 sort(),默认可排字母顺序。sort(compareFn(a, b))其中compareFn(a, b)返回的值若大于0则a在b的后面。 reduce(),最复杂。reduce(func(){上一轮计算出的结果…

Flink-SQL 写入PostgreSQL 问题汇总

​ 1.主键字段为空问题 错误信息 org.apache.flink.table.api.TableException: Column bus_no is NOT NULL, however, a null value is being written into it. You can set job configuration table.exec.sink.not-null-enforcerDROP to suppress this exception and drop …

罗技k380键盘教程

在智能手机和平板电脑上享受台式电脑般舒适便捷的输入体验。罗技蓝牙™ 多设备键盘 K380 是一款小巧独特的键盘,让您在家中任何地方都能使用个人设备进行沟通和创作。 借助便捷的易于切换™ 按钮,可以通过蓝牙™ 无线技术同时连接最多三台设备&#xff…

【实用技巧】使用USB数据线向亚马逊kindle导入电子书

一、内容简介 本文主要介绍如何使用USB数据线向亚马逊kindle阅读器导入电子书。 二、所需原料 笔记本电脑、Kindle阅读器、Kindle适配的USB-a数据线。 三、导入方法 1、使用USB-a数据线将Kindle阅读器与电脑连接。 2、找到Kindle文件夹-documents-Downloads-Items1目录。…

Django框架实现简单的接口开发

前提创建一个Django项目&#xff0c;目录如下&#xff1a; Django框架上进行GET请求接口开发示例: 1.在上面项目结构目录Template下&#xff0c;新建一个login.html页面&#xff0c;定义表单提交请求的方式为post&#xff0c;具体代码如下。 <!DOCTYPE HTML> <html …

freemarker 使用word模板赋值

1. 引包<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.28</version></dependency>word文档工具类import freemarker.template.Configuration; import freemarker.template.…

快来看看Java在编程语言中的优势与特性吧

作者主页&#xff1a;paper jie的博客_CSDN博客-C语言,算法详解领域博主 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 其他专栏&#xff1a;《系统解析C语言》《C语言》《C语言-语法篇》 内容分享&#xff1a…

CentOS 7.9 安装 Jenkins

CentOS 7.9 安装 Jenkins 文章目录 CentOS 7.9 安装 Jenkins一、概述二、安装1、安装 OpenJDK2、安装 Jenkins3、启动 Jenkins4、给 Jenkins 放行端口 三、初始化 Jenkins 配置1、访问2、解锁 Jenkins3、配置清华大学的源地址4、安装插件5、创建管理员用户6、完成安装 四、功能…

【C++】C++关于异常的学习

文章目录 C语言传统的处理错误的方式一、异常的概念及用法二、自定义异常体系总结 C语言传统的处理错误的方式 传统的错误处理机制&#xff1a; 1. 终止程序&#xff0c;如 assert &#xff0c;缺陷&#xff1a;用户难以接受。如发生内存错误&#xff0c;除 0 错误时就会终止…

三相一次重合闸程序逻辑原理(二)

在手动合闸至故障线路或手动分闸及保护或自动装置要求不允许重合闸&#xff08;如母线、变压器保护及低频减载动作&#xff09;等情况下&#xff0c;闭锁重合闸的输入开关量触点接通&#xff0c;H4输出“1”&#xff0c;非门Z4输出“0”&#xff0c;计数器清零&#xff08;CD0&…