Bean 作用域与生命周期

Bean 作用域与生命周期

​ 对于 Spring 来说,核心操作对象就是存和取 Bean ,接下来就 Bean 的作用域与生命周期进行探讨。

文章目录

  • Bean 作用域与生命周期
    • 一、作用域的定义
      • 1.1、Bean 的6种作用域
      • 1.2、Bean作用域设置方法
    • 二、Bean 的生命周期
      • 2.1、Bean 的执行流程
      • 2.2、Bean 的生命周期分为5大部分 ☆

通过例子看作用域:

1、先在Spring IoC 容器中存放一个 Bean(公共 Bean);

@Component
public class StudentComponent {@Beanpublic Student studentNum1() {Student student = new Student();student.setId(1);student.setName("java"); //student.setPassword("123");return student;}
}

​ 这段代码表示在 Spring IoC 容器中已经存上了一个 Bean 对象 并且 对象的 id 设置成 1,对象的 name 设置成了 java;对象的 password 设置成了 123.

2、A用户来取出 Spring IoC 容器中的这个 Bean 对像进行了修改操作;

@Controller
public class StuedntControllerA {@Autowiredprivate Student student;public Student getStudent() {System.out.println("修改 student 信息");student.setPassword("456");student.setName("python");student.setId(2);return student;}
}

​ 这段代码表示A用户取出容器中的 Bean 对象之后又再次基础上修改了 Bean对象里面的信息,password 改成为456,name改成了 python。

3、B用户什么也不操作只是在 Spring IoC 容器中取出 Bean 对象。

@Controller
public class StudentControllerB {@Resourceprivate Student student;public Student getStudent() {return student;}
}

​ 平常我们会认为 A 用户在 Spring IoC 容器中里面取出的对象做出了修改,可以修改成功,变成修改之后的样子,而 B 用户他没有任何操作只是从 Spring IoC 里面取出了 Bean 对象,故里面的数据还是原来 Bean 对象的数据。

但是我们还是要运行程序看结果:

image-20230718105011219

最后的结果:是 A 用户确实修改了信息,但是 B 用户的信息取得是 A 用户的信息。

原因分析:
因为在默认情况下 Bean 是单例模式(singleton),也就是所有人使用的都是同一个对象,使用单例模式好处之一就是可以很大程度的提高性能 ,所以在 Spring 中 Bean 的作用域默认是 singleton 单例模式。

image-20230718113924996

​ 都是同一个对象 Bean。而 Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种行为模式,比如 上面singleton 单例作⽤域,就表 示 Bean 在整个 Spring 中只有⼀份,它是全局共享的,那么当其他⼈修改了这个值之后,那么另⼀个 ⼈读取到的就是被修改的值。

一、作用域的定义

​ 限定程序中变量的可用范围叫做作用域,或者说在源代码中定义变量的某个区域就叫做作用域。

1.1、Bean 的6种作用域

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

  • singleton:单例作用域(Spring 支持)
  • prototype:原型作用域(多例作用域)(Spring 支持)
  • request:请求作用域(Spring MVC 生效)
  • session:会话作用域(Spring MVC 生效)
  • application:全局作用域(Spring MVC 生效)
  • websocket:Http WebSocket 作用域(Spring MVC 生效)了解

​ 这篇的后面四个都是用在 Spring MVC 里面的,Spring MVC 在 Spring 中也是一个非常重要的框架,后面也会了解到,这篇主要看看 Spring 支持的,其中 singleton 已经了解到了,接下来就是 prototype。

prototype 描述:每次对该作用域下的 Bean 请求都会创建新的实例:获取 Bean(getBean方法)及装配 Bean (通过@Autowired注入)都是新的对象实例。

所以说适用上面的情况,创建出新的实例,不会影响 A 用户修改了Bean 之后,B 用户再去拿,就是原先 Bean 对象里面的数据不会改变。

1.2、Bean作用域设置方法

使用 @Scope 标签 可以用来声明 Bean 的作用域,比如设置 Bean 的作用域。

1、直接写 String 类行的作用域

@Scope("prototype")

2、使用全局的参数

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

代码如下:

@Component
public class StudentComponent {
//    @Scope("prototype") 方式一@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) // 方式二@Beanpublic Student studentNum1() {Student student = new Student();student.setId(1);student.setName("java");student.setPassword("123");return student;}
}

image-20230718142214451

这样使用多列模式 prototype B 用户就不会受到影响

二、Bean 的生命周期

2.1、Bean 的执行流程

​ Bean 的执行流程(Spring 的执行流程):启动 Spring 容器 ——> 实例化 Bean (创建 Bean ,分配内存空间)——> Bean 注册到 Spring 中(存)——> 将 Bean 装配到需要的类中(取)。

在这里插入图片描述

Spring Core 执行流程:

​ 1、启动 Spring 容器(main方法)

​ 2、加载 XML,实例化并申请内存

​ 3、将添加了5大注解的对象存储到容器中。

​ 4、将存储的 Bean 中的注入的对象属性进行初始化。

2.2、Bean 的生命周期分为5大部分 ☆

Bean 的生命周期(从 Bean 诞生到销毁的整个过程)(☆☆☆☆☆)

1、实例化 Bean 对象,只是申请内存空间;

2、先设置 Bean 属性 (依赖注入和+装配)

3、再对 Bean 初始化

  • 各种 Aware 感知:BeanNameAware、BeanFactoryAware…的接口方法
  • 初始化前置方法(BeanPostProcessor)
  • 构造器方法 @PostConstruct 初始化方法 (依赖注入操作之后被执行)☆
  • init-method 初始化方法 (xml)
  • 初始化后置方法(BeanPostProcessor)

实力化 和 初始化的区别

实例化和属性设置是 Java 级别的系统“事件”,其操作过程不可人工干预和修改;而初始化是给 开发者提供的,可以在实例化之后,类加载完成之前进⾏⾃定义“事件”处理。

4、使用 Bean

5、销毁 Bean

  • @PreDestroy
  • destroy-method

再对 Bean 初始化里面的东西进行解释:

1、Aware 这个就是一个感知通知,映射关系,比如说在方法注解@Bean(“pwd”)上面使用了别名 Aware需要找对应关系通知映射

2、为什么设置 Bean 属性在初始化前面,因为只有被类注入,初始化的时候不会因为需要类的其他属性报错。

3、初始化方法 @PostConstruct 和 init-method 本质上上一样的,是不同时期的产物,程序员@PostConstruct 可以根据业务配置初始化条件,属于是注解Spring 时期的;init-method 是 xml 时期的,比较远古。

4、这也对应了销毁 Bean 里面的@PreDestroy和destroy-method

生命周期演示代码

@Component
public class BeanLife implements BeanNameAware {@Overridepublic void setBeanName(String s) {System.out.println("执行:BeanNameAware setBeanName 方法:"+s);}// 初始化方式一:@PostConstruct@PostConstructpublic void postConstruct() {System.out.println("执行了:@PostConstruct");}// 初始化方式二:init-methodpublic void init(){System.out.println("执行了:init-method"); //要是用 xml 配置 <Beans>里面的标签}// 销毁方法一:@PreDestroypublic void preDestroy(){System.out.println("执行了:preDestroy");}//销毁方式二:public void myDestroy(){System.out.println("执行了:myDestroy"); //要是用 xml 配置 <Beans>里面的标签}}

xml配置如下:

<?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"><!-- 配置一下:bean注解扫描的根路径(方面后面更简单存储对象到spring容器)--><content:component-scan base-package="com.yuanye.beans"></content:component-scan><beans><bean id="beanLife" class="com.yuanye.beans.Component.BeanLife" init-method="init"destroy-method="myDestroy"></bean></beans>
</beans>

特别注意 < Beans > 里面的配置

调用类方法:

public class App {public static void main(String[] args) {// 是ApplicationContext的子类,获得 spring 上下文对象ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("spring-config.xml");BeanLife beanLife = context.getBean("beanLife",BeanLife.class);System.out.println("使用 Bean");System.out.println("销毁 Bean");context.destroy();}
}

image-20230718164518886

流程图如下:

image-20230718165228073


总结:

​ 本篇文章介绍了 Bean 的6种作用域和 Bean 的执行流程,还有重要的 Bean 的生命周期,生命周期里面的实例化和初始化是不一样的,一个是不能人控制,一个是可以人为控制;Bean 的生命周期里面特别是初始化环节很重要。

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

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

相关文章

postgresql还原bak

1、第一步肯定是要新建自己还原的目标数据库&#xff0c;例如&#xff1a; 2、进入postgresql的安装目录下的bin目录下 然后地址栏输入cmd进入命令 输入以下 psql -h localhost -U postgres -p 5432 -d SamsinoYardStandard_karamay -f "D:\desktop\zk\20230628.bak&quo…

verilog实现数码管静态显示

文章目录 verilog实现数码管静态显示一、任务要求二、实验代码三、仿真代码四、仿真结果五、总结 verilog实现数码管静态显示 一、任务要求 六个数码管同时间隔0.5s显示0-f。要求&#xff1a;使用一个顶层模块&#xff0c;调用计时器模块和数码管静态显示模块。 二、实验代码…

将Spring Boot项目打包部署到阿里云linux服务器

首先 你要保证自己的服务器上有java环境 如果没有可以参考我的文章 linux服务器中安装java JDK1.8版本 然后 我们打开我们的Spring Boot项目 双击 package 生命周期进行打包 打包完成之后 我们找到 target 下面会有一个jar包 然后 我们右键它 如下图操作 系统就会帮你打开它所…

OpenCV for Python 学习第四天 :通道的获取与合并

上一篇博客&#xff0c;我们学习了如何通过更快的item()和itemset()的方法访问图片&#xff0c;以及了解了图像的兴趣位置的获取方法&#xff0c;那么今天&#xff0c;我们将学习通道的处理方法&#xff0c;通过通道的拆分和合并的实例&#xff0c;让大家更好的了解咱们有关于B…

前端笔记_OAuth规则机制下实现个人站点接入qq三方登录

文章目录 ⭐前言⭐qq三方登录流程&#x1f496;qq互联中心创建网页应用&#x1f496;配置回调地址redirect_uri&#x1f496;流程分析 ⭐思路分解⭐技术选型实现&#x1f496;技术选型&#xff1a;&#x1f496;实现 ⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本…

JMeter做http接口功能测试

1. 普通的以key-value传参的get请求 e.g. 获取用户信息 添加http请求&#xff1b;填写服务器域名或IP&#xff1b;方法选GET&#xff1b;填写路径&#xff1b;添加参数&#xff1b;运行并查看结果。 2. 以Json串传参的post请求 e.g. 获取用户余额 添加http请求&#xff1b;…

设计模式-原型模式

目录 一、传统方式 二、原型模式 三、浅拷贝和深拷贝 克隆羊问题&#xff1a; 现在有一只羊tom&#xff0c;姓名为: tom,年龄为: 1&#xff0c;颜色为: 白色&#xff0c;请编写程序创建和tom羊属性完全相同的10只羊。 一、传统方式 public class Client {public static vo…

WMTS 地图切片Web服务 协议数据解析

1. WMTS 描述 WMTS(Web Map Tiles Service):地图切片Web服务。 2. 数据示例&#xff1a; arcgis online 导出的wmts xml&#xff1a; https://sampleserver6.arcgisonline.com/arcgis/rest/services/WorldTimeZones/MapServer/WMTS 内容解析&#xff1a; contents中可能包…

J2EEJSP自定义标签库01out标签if标签

目录 一.什么是标签 二.JSP自定义标签库 2.1 JSP标签库是什么 2.2 处理流程 2.3 如何自定义标签 2.4 标签类型 三.开发示例 3.1 out标签 1.创建助手类 2.编写tld&#xff08;标签库的描述&#xff09;文件&#xff0c;&#xff08;必须放在WEB-INF目录或其目录下&a…

python爬虫-获取headers(报文头)关键参数实例小记

注意&#xff01;&#xff01;&#xff01;&#xff01;某XX网站逆向实例仅作为学习案例&#xff0c;禁止其他个人以及团体做谋利用途&#xff01;&#xff01;&#xff01; 第一步&#xff1a;请求页面&#xff0c;得到响应。建议首次请求时headers内容都带着&#xff0c;调试…

react报错信息

报错信息 render函数里dom不能直接展示obj对象 取变量记得要有{} https://segmentfault.com/q/1010000009619339 这样在写的时候就已经执行方法了&#xff0c;所以此处用箭头函数&#xff08;&#xff09;》{}才会在点击时执行或者 遍历数据使用map来遍历&#xff0c;使用forea…

Docker【安装与基本使用】

【1】Docker的安装 注意&#xff1a;如果之前安装过docker其他版本&#xff0c;请删除干净。 docker-01 10.0.0.51 2G docker-02 10.0.0.52 2G docker-01 [rootdocker-01 ~]# cp -rp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime cp: overwrite ‘/etc/localtime’? …

H3C-Cloud Lab实验-OSPF配置实验

一、实验拓扑图 实验需求&#xff1a; 1、按照图示配置 IP 地址 2、按照图示分区域配置 OSPF &#xff0c;实现全网互通 3、为了路由结构稳定&#xff0c;要求路由器使用环回口作为 Router-id&#xff0c;ABR 的环回口宣告进骨干区域 4、掌握OSPF初始化流程、路由表学习的过…

el-progress组件使用,样式修改,自定义文字

正常的el-progress显示是这样的 修改后 自动计算percentage&#xff0c;format自定义显示文字 <template><div><div class"content-view"><div v-for"(item, index) in progressList" class"item-view"><el-prog…

解锁编程世界的魔法密码:探索算法的奥秘与应用

一个程序员一生中可能会邂逅各种各样的算法&#xff0c;但总有那么几种&#xff0c;是作为一个程序员一定会遇见且大概率需要掌握的算法。今天就来聊聊这些十分重要的“必抓&#xff01;”算法吧~* 一&#xff1a;引言 算法是解决问题和优化程序性能的核心&#xff0c;它是一…

你真的会用async和await么?

async函数搞懂 背景asyncawaitawait 知识点1await 知识点2await 知识点三await 知识点四await 知识点五 背景 背景就是遇到了一个比较烦人的模块&#xff0c;里面的涉及到了大量的async 和 awiat。发现大多人对这个语法糖一知半解&#xff0c;然后大量的滥用&#xff0c;整理一…

数据标注的类型有哪些?

构建像人类一样的AI或ML模型需要大量训练数据。要使模型做出决定并采取行动&#xff0c;就必须通过数据标注来训练模型&#xff0c;使其能够理解特定信息。 但是&#xff0c;什么是数据标注呢&#xff1f;数据标注是指对用于人工智能应用的数据进行分类和标注。我们必须针对特定…

Qt6 Qt Quick UI原型学习QML第二篇

Qt6 Qt Quick UI原型学习QML第二篇 界面效果QML语法语法讲解核心要素项目元素矩形元素文本元素图像元素MouseArea元素 界面效果 QML语法 import QtQuick 2.12 import QtQuick.Window 2.12Window {id: rootvisible: truewidth: 640height: 480title: qsTr("QML学习第二篇&…

用微服务架构推进企业数字化转型升级

随着数字化转型进入深水区&#xff0c;企业应用程序建设需求急剧增长且变化多端&#xff0c;软件架构经历了单体结构、垂直架构、SOA架构&#xff0c;发展到了现在的微服务架构。 单体架构目前应用较多&#xff0c;部署容易&#xff0c;但单体式应用内部包含了所有需要的服务&…

FPGA——点亮led灯

文章目录 一、实验环境二、实验任务三、实验过程3.1 编写verliog程序3.2 引脚配置 四、仿真4.1 仿真代码4.2仿真结果 五、实验结果六、总结 一、实验环境 quartus18.1 vscode Cyclone IV开发板 二、实验任务 每间隔1S实现led灯的亮灭&#xff0c;实现流水灯的效果。 三、实…