【Spring】——Spring生命周期

news2024/10/7 11:29:02

前言

❤️❤️❤️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的重要环节,它们各自都有着不同的作用和实现方式。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

XML文件原理详解

文章目录 一、简介1. XML定义2. 测试3. HTML和XML的区别 二、XML基本语法1. 语法规则2. 元素的属性3. CDATA4. DTD文件5. XSD文件 三、Java解析XML1. 简介2. 解析XML文件 四、Xpath1. 简介2. Xpath的使用 一、简介 1. XML定义 XML(可扩展标记语言)是一…

高压放大器在介电材料中的应用有哪些

高压放大器是一种能够输出高电压的放大器,具有多种应用,其中之一就是在介电材料中的应用。介电材料是指能够保持一定电荷和电场状态的物质,其特点包括绝缘性、极化性和介电常数等。下面安泰电子将详细介绍高压放大器在介电材料中的应用。 介电…

《HarmonyOS开发 – OpenHarmony开发笔记(基于小型系统)》第4章 OpenHarmony应用开发实例

开发环境: 开发系统:Ubuntu 20.04 开发板:Pegasus物联网开发板 MCU:Hi3861 OpenHarmony版本:3.0.1-LTS 4.1新建工程及配置 1.新建工程及源码 新建目录 $ mkdir hello在applications/sample/myapp中新建src目录以及…

【零基础学机器学习 5】机器学习中的分类:什么是分类以及分类模型

👨‍💻 作者简介:程序员半夏 , 一名全栈程序员,擅长使用各种编程语言和框架,如JavaScript、React、Node.js、Java、Python、Django、MySQL等.专注于大前端与后端的硬核干货分享,同时是一个随缘更新的UP主. 你可以在各个…

华为OD机试真题 JavaScript 实现【字符串加密】【2023Q1 100分】,附详细解题思路

一、题目描述 有一种技巧可以对数据进行加密,它使用一个单词作为它的密匙。下面是它的工作原理:首先,选择一个单词作为密匙,如TRAILBLAZERS。如果单词中包含有重复的字母,只保留第1个,将所得结果作为新字母…

Spark大数据处理学习笔记(2.4)IDEA开发词频统计项目

该文章主要为完成实训任务,详细实现过程及结果见【http://t.csdn.cn/0qE1L】 文章目录 一、词频统计准备工作1.1 安装Scala2.12.151.2 启动集群的HDFS与Spark1.3 在HDFS上准备单词文件 二、本地模式运行Spark项目2.1 新建Maven项目2.2 添加项目相关依赖2.3 创建日志…

009:vue中el-table删除当前行的代码示例

第009个 查看专栏目录: VUE — element UI echarts,openlayers,cesium,leaflet,mapbox,d3,canvas 免费交流社区 专栏目标 在vue和element UI联合技术栈的操控下,本专栏提供行之有效的源代码示例…

计算机网络(网络层,传输层,应用层,复习自用)

计算机网络 网络层网络层功能IP数据报格式IP数据报分片IPV4地址网络地址转换(NAT)子网划分与子网掩码无分类编址CIDRARP协议DHCP协议ICMP协议IPV6路由算法及路由协议RIR协议及距离向量算法OSPF协议及链路状态算法BGP协议IP组播移动IP网络层设备 传输层传…

Linux 部署Java项目-jar包和war包(五)

文章目录 一、前景(jar包和war包区别)一、部署jar包程序1. 项目打成jar包①方式一:使用idea工具打包项目②方式二:通过cmd命令的方式打包项目 2. 项目命令启动① 查看之前启动的程序,关闭之② 启动程序③ 验证是否部署…

Vue中如何进行数据筛选与搜索功能实现

Vue中如何进行数据筛选与搜索功能实现 在Vue应用中,数据筛选和搜索是常见的需求。本文将介绍如何在Vue中进行数据筛选和搜索功能的实现,包括基于原生JavaScript的筛选和搜索、基于Lodash库的筛选和搜索、以及基于Vue插件的筛选和搜索。 基于原生JavaScr…

Hazel游戏引擎(012)GLFW窗口事件

文中若有代码、术语等错误,欢迎指正 文章目录 前言如何确定GLFW窗口事件的回调函数参数Application接收事件回调流程原项目流程(12345)自己写的简单Demo与流程(123) 前言 此节目的 为了完成008计划窗口事件的接收glfw窗口事件以及回调部分 此节要完成 使用glfw函数…

C语言之指针初阶(1)

本章重点 1. 指针是什么 2. 指针和指针类型 3. 野指针 4. 指针运算 5. 指针和数组 6. 二级指针 7. 指针数组 今天我们讲解前4个稍微简单一点的内容,下一篇博客讲解后三部分 首先引入话题 我们口语讲到指针,比如p指针,其实想要…

【0基础自研记录】ESP32-CAM自制个人网络监控

目的:实现一个小型家庭监控 一、前期准备 1.硬件准备 esp32-acm烧录板烧录线 2.软件准备 Arduion IDE CH340串口驱动 下载地址如下 Arduion IDE:https://www.arduino.cc/en/software CH340串口驱动 链接:https://pan.baidu.com/s/1ri8dK7wW6KFz8rOPs…

已知一个整数,如何判断这个整数是无符号的?

前言 记录6月11日,肯哥在群里面分享的一个问题。说实话,看到题目想了半天没明白。一看答案,才发现,这题真的简单。 题目 已知一个整数,如何判断这个整数是无符号的? 题解 (1)因为我的…

JVM相关特性

每个使用Java的开发者都知道Java字节码是在JRE中运行(JRE: Java 运行时环境)。JVM则是JRE中的核心组成部分,承担分析和执行Java字节码的工作,而Java程序员通常并不需要深入了解JVM运行情况就可以开发出大型应用和类库。尽管如此,如果你对JVM有…

008:vue中el-upload不显示上传的文件列表

第008个 查看专栏目录: VUE — element UI echarts,openlayers,cesium,leaflet,mapbox,d3,canvas 免费交流社区 专栏目标 在vue和element UI联合技术栈的操控下,本专栏提供行之有效的源代码示例…

废柴日记8:从入门到入狱的Python爬虫学习笔记1(入门篇)

前言:我错了,但下次也不一定(●’◡’●) 米娜桑,好久不见,不知道这段时间各位手中的西瓜刀有没有按时擦亮呢? 我也是在摸爬滚打将近一年之后总算是找到了一点人生的方向所以当成救命稻草现在正死死握紧不放手的啊。…

【Windows 系统笔记】使用服务器运行装载AList+本地安装RaiDrive进行网盘本地挂载

文章目录 前言准备工作一、购买一台云服务器配置服务器安装宝塔面板新建网站进入当前目录 二、安装AList三、登录四、开启域名访问五、挂载阿里云盘刷新令牌 六、使用RaiDrive挂载到本地 前言 大家肯定很好奇我为什么要写一篇这样的文章,因为之前一直使用本地挂载网…

SQL索引

一、索引概述 介绍: 索引是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以…

【数据结构与算法】04 哈希表 / 散列表 (哈希函数、哈希冲突、链地址法、开放地址法、SHA256)

一种很好用,很高效,又一学就会的数据结构,你确定不看看? 一、哈希表 Hash Table1.1 核心概念1.2 哈希函数 Hash Function1.3 哈希冲突 Hash Collision1.4 哈希冲突解决1.41 方法概述1.42 链地址法 Separate Chaining1.43 开放寻址…