Bean的作用域和生命周期

1. Bean的作用域

前引例子4

现在有一个公共的Bean对象,提供给A用户和B用户使用,然而在使用的时候A用户将Bean对象的数据进行修改,此时B得到的Bean对象是否是原来的Bean对象呢?

@Component
	public class Users {
		@Bean
		public User user() {
			User user = new User();
			user.setId(1);
			user.setName("张三");
			return user;
		}
	}
@Controller
public class BeanScopeController {
    @Resource
    private User user;

    public User getUser() {
        User user1 = user;
		//修改
        user1.setId(2);
        user1.setName("李四");
        return user1;
    }
}
@Controller
public class BeanScopeController2 {
    @Resource
    private User user;

    public User getUser() {
        User user2 = user;
        return user2;
    }
}
public class App {
	public static void main(String[] args) {
		ApplicationContext context =
			new ClassPathXmlApplicationContext("spring-config.xml");
		//修改前的Bean对象
		User user = context.getBean("user", User.class);
		System.out.println("Bean对象修改前: " + user.toString() );
		//A修改Bean对象后
		BeanScopeController beanScopeController =
			context.getBean("beanScopeController", BeanScopeController.class);
		System.out.println("A对象修改后: " + beanScopeController.getUser().toString());
		//B从Spring中获取Bean对象,看是修改前的值还是没有被修改
		BeanScopeController2 beanScopeController2 =
			context.getBean("beanScopeController2", BeanScopeController2.class);
		System.out.println("B对象修改后: " + beanScopeController2.getUser().toString());
	}
}

image.png
我们发现A对象修改Bean对象后,B对象从Spring中获取的Bean对象也跟着改变了。

why?

这是因为Spring的Bean对象默认情况下是单例状态(singleton),也就是所有人使用的都是同一个对象。Spring采用单例模式可以提高性能,所以Bean的默认作用域就是singleton单例模式。

什么是作用域

在之前的JavaSE时,一个临时变量出了大括号就销毁,意味着临时变量的作用域就是在这个大括号内。而Bean的作用域是指Bean在Spring框架中某种行为模式,比如上面的singleton单例作用域,就表示Bean在Spring中只有一份,他是全局共享的,当其他人修改了这个值之后,那么另外一个人读取到的就是修改后的值。

Bean的6种作用域
  1. singleton:单例作用域
  2. prototype: 原型作用域(多例作用域)
  3. request: 请求作用域
  4. session:会话作用域
  5. application: 全局作用域
  6. websocket: Http WebSocket作用域

在普通的Spring项目中只有前两种,后四种状态是Spring MVC中的值。

singleton

描述:咱们上面演示了,singleton单例作用域下的Bean在IOC容器中只存在一个实例,获取Bean和装配Bean都是同一个对象
场景:通常无状态的Bean使用单例作用域(无状态表示Bean对象的属性状态不需要更新)

prototype

描述:每次对该作用域下的Bean的请求都会创建新的实例,获取Bean以及装配Bean都是新的对象实例
场景:通常有状态的Bean使用该作用域,也就是Bean对象的属性状态需要更新的时候

request

描述:每次http请求会创建新的Bean实例,类似于prototype
场景: 一次http的请求和响应共享同一个Bean对象

session

描述: 在一个http session中,定义一个Bean对象
场景: 用户会话中共享一个Bean对象,例如记录一个用户的登入信息

application(了解)

描述: 在一个http servlet Context中,定义一个Bean实例
场景: Web应用的上下文信息,记录一个应用的共享信息
:::danger
singleton和application的区别
:::

  1. singleton是Spring core的作用域,而application是Spring web的作用域
  2. singleton作用域IOC容器,而application作用于Servlet容器
websocket(了解)

描述:在一个http webSocket的生命周期中,定义一个Bean对象
场景:WebSocket的每次会话中,保存一个Map结构的头信息,将用来包裹客户端消息头,第一次初始化后,直到WebSocket结束都是同一个Bean

设置作用域

使用@Scope标签声明Bean的作用域

@Component
public class Users {
    // 设置为原型模式/多例模式
    @Scope("prototype")
    @Bean
    public User user() {
        User user = new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }
}

image.png
修改为多例模式后,A对象的修改不影响B对象的使用
@Scope 标签即可以修饰方法也可以修饰类,@Scope 有两种设置方式:

  1. 直接设置值: @Scope(“prototype”)
  2. 使用全局变量设置: @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

2. Spring的执行流程

  1. 启动Spring容器

image.png

  1. 实例化Bean(分配内存空间)
    1. 使用xml注册bean
    2. 配置bean的扫描路径

扫描xml中配置的路径,告知Spring加载的时候要将哪些对象注入到容器中

  1. 将Bean存储到spring中,通过类注解/方法注解进行装配

image.png

  1. 将bean从spring中读取出来,装配到相应的类中

image.png

3. Bean的生命周期

生命周期就是一个对象从创建到销毁的整个生命过程,我们把这个过程叫做一个对象的生命周期。
Bean的生命周期可以分为5个部分

  1. 实例化Bean:从无到有,将字节码转为内存中的对象,只分配了内存空间。这就类似于自己买了个毛坯房,里面是空的,只有空间
  2. 设置属性:类属性的加载,Bean的注入和装配。这就类似于装修之前购买装修材料
  3. 初始化:
    1. 各种通知,如使用BeanNameAware方法,类似于装修房子之前打电话叫各种师傅来施工
    2. 初始化的前置工作,类似于师傅到了现场,要勘察环境,制定装修方案
    3. 进行初始化工作,如使用@PostConstruct初始化(注解时代),使用init-method初始化(xml时代)。类似于有两类师傅,一类是凭科技干活,一类是凭经验干活的
    4. 初始化的后置工作,类似于装修之后的清理工作
  4. 使用Bean,类似于拎包入住
  5. 销毁Bean 如使用@PreDestroy, 类似于卖掉房子
    :::danger
    验证Bean的生命周期
    :::
@Component
	public class BeanLifeComponent implements BeanNameAware {
		//通知
		@Override
		public void setBeanName(String s) {
			System.out.println("执行了通知");
		}
		//进行初始化工作
		@PostConstruct
		public void postConstruct() {
			System.out.println("执行了PostConstruct");
		}

		public void init() {
			System.out.println("执行了init-method");
		}

		@PreDestroy
		public 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="component"></content:component-scan>
	<bean id="beanLifeComponent"  class="component.BeanLifeComponent"
		init-method="init"></bean>
</beans>
public static void main(String[] args) {
	ClassPathXmlApplicationContext context =
		new ClassPathXmlApplicationContext("spring-config.xml");
	BeanLifeComponent bean = context.getBean(BeanLifeComponent.class);
	System.out.println("使用Bean");
	bean.preDestroy();
}

image.png
验证了在初始化阶段,先执行通知,执行初始化工作时,先执行注解时代,在执行xml时代;再使用Bean,销毁bean对象。
:::info
验证设置属性是在初始化之前
:::

@Service
public class UserService {
	public UserService() {
		System.out.println("执行了UserService的构造方法");
	}
	public void sayHi() {
		System.out.println("hello UserService");
	}
}
@Controller
public class UserController {
    @Resource
    private UserService service;

    @PostConstruct
    public void postConstruct() {
        service.sayHi();
        System.out.println("执行了UserController的构造方法");
    }

}
public static void main(String[] args) {
	ApplicationContext context =
		new ClassPathXmlApplicationContext("spring-config.xml");
	UserController userController = context.getBean("userController", UserController.class);
}

image.png
由于是先设置属性的,所以在UserController在Bean注入是比执行初始化方法@PostConstruct 早,因此先输出“执行了UserService的构造方法”。而且如果不是先设置属性,那么service就是null,就会报空指针异常。

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

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

相关文章

人工智能原理复习--搜索策略(二)

文章目录 上一篇启发式搜索与或图搜索博弈下一篇 上一篇 人工智能原理复习–搜索策略&#xff08;一&#xff09; 启发式搜索 提高一般图搜索效率的关键是优化OPEN表中节点的排序方式 最理想的情况是每次排序OPEN表表首n总在解答路径上 全局排序–对OPEN表中的所有节点进行…

馆藏档案管理系统和数字档案管理系统的区别

馆藏档案管理系统是指传统的档案管理系统&#xff0c;主要包括档案馆内纸质档案的收集、整理、存储、保护、利用等工作。它的主要特点是针对纸质档案的管理&#xff0c;需要建立大量的文件柜、卷宗和保管设备&#xff0c;检索和借阅需要现场操作。 专久智能数字档案管理系统则是…

文献速递:多模态影像组学文献分享:多模态图注意力网络用于COVID-19预后预测

文献速递&#xff1a;多模态影像组学文献分享&#xff1a;多模态图注意力网络用于COVID-19预后预测 01 文献速递介绍 在处理像 COVID-19 这样的新出现的疾病时&#xff0c;患者和疾病特定因素&#xff08;例如&#xff0c;体重或已知共病&#xff09;对疾病的即时进展的影响…

使用智能AI文心一言处理采集数据

简数采集器支持调用百度智能AI文心一言大模型API接口&#xff0c;可对采集的数据进行研究分析&#xff0c;内容创作。 文心一言API使用方法如下&#xff1a; 目录 1. 采集数据 2. 申请API 3. 对接文心一言API 4. 设置文心一言API的执行指令 5. 使用文心一言API处理采集数…

案例061:基于微信小程序的互助学习系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

54.grpc实现文件上传和下载

文章目录 一&#xff1a;简介1. 什么是grpc2. 为什么我们要用grpc 二&#xff1a;grpc的hello world1、 定义hello.proto文件2、生成xxx_grpc.pb.go文件3、生成xxx.pb.go结构体文件4、编写服务代码service.go5、编写客户端代码client.go 三、服务端流式传输&#xff1a;文件下载…

pycharm安装

1.先去官网下载pycharm 2.下载python3.8 3.修改pip镜像 4.如果有环境变量没加的加一下

一加 12 Pop-up快闪活动来袭,十城联动火爆开启

12 月 9 日&#xff0c;一加 12 Pop-up 快闪活动在北京、深圳、上海、广州等十城联动开启&#xff0c;各地加油欢聚快闪现场&#xff0c;抢先体验与购买一加 12。作为一加十年超越之作&#xff0c;一加 12 全球首发拥有医疗级护眼方案和行业第一 4500nit 峰值亮度的 2K 东方屏、…

我尝试用 AI 来做数据分析,结果差强人意!

大家好&#xff0c;我是木川 工作中经常会需要分析数据 1、统计分析&#xff0c;计算某项指标的均值、分位数、标准差等 2、相关性分析&#xff0c;比如分析销售额与顾客年龄、顾客性别、促销活动等的相关性 3、可视化分析&#xff0c;比如绘制柱状图、折线图、散点图等 有了 A…

Java网络编程——对象的序列化与反序列化

当两个进程进行远程通信时&#xff0c;彼此可以发送各种类型的数据&#xff0c;如文本、图片、语音和视频等。无论是何种类型的数据&#xff0c;都会以二进制序列的形式在网络上传送。当两个Java进程进行远程通信时&#xff0c;一个进程能否把一个Java对象发送给另一个进程呢&a…

本地部署语音转文字(whisper,SpeechRecognition)

本地部署语音转文字 1.whisper1.首先安装Chocolatey2.安装3.使用 2.SpeechRecognition1.环境2.中文包3.格式转化4.运行 3.效果 1.whisper 1.首先安装Chocolatey https://github.com/openai/whisper 以管理员身份运行PowerShell Set-ExecutionPolicy Bypass -Scope Process -…

自动化测试框架性能测试报告模板

一、项目概述 1.1 编写目的 本次测试报告&#xff0c;为自动化测试框架性能测试总结报告。目的在于总结我们课程所压测的目标系统的性能点、优化历史和可优化方向。 1.2 项目背景 我们公开课的性能测试目标系统。主要是用于我们课程自动化测试框架功能的实现&#xff0c;以及…

记录 | ubuntu监控cpu频率、温度等

ubuntu监控cpu频率、温度等 采用 i7z 进行监控&#xff0c;先安装&#xff1a; sudo apt install i7z -ysudo i7z

基于51单片机的多模式智能闹钟系统【代码+仿真+论文+PPT等16个文件资料】

一、项目功能简介 整个设计系统由STC89C52单片机LCD1602显示模块DS1302模块温度模块存储模块矩阵按键模块组成。 具体功能&#xff1a; 1、智能闹钟正常模式显示阳历年、月、日、星期、小时、分、秒&#xff1b; 2、可设置时间和日期&#xff1b; 3、 LCD显示当前温度&…

游戏玩家升级不伤手之选,光威龙武系列超强性能

得益于国产存储芯片的崛起&#xff0c;现在的内存条价格太香了。要放在前几年&#xff0c;购买内存条时都会优先考虑国际一线品牌。随着内存条行业发生巨变&#xff0c;国产品牌光威GLOWAY&#xff0c;是全球前三的内存模组厂商嘉合劲威旗下品牌&#xff0c;它推出的内存条产品…

十八、FreeRTOS之FreeRTOS任务通知

本节需要掌握以下内容&#xff1a; 1、任务通知的简介&#xff08;了解&#xff09; 2、任务通知值和通知状态&#xff08;熟悉&#xff09; 3、任务通知相关API函数介绍&#xff08;熟悉&#xff09; 4、任务通知模拟信号量实验&#xff08;掌握&#xff09; 5、任务通知…

JOSEF约瑟 接触式中间继电器 JZC1-53 AC220V 导轨安装

系列型号 JZC1-22中间继电器&#xff1b;JZC1-44中间继电器&#xff1b; JZC1-62中间继电器&#xff1b;JZC1-80中间继电器&#xff1b; JZC1-71中间继电器&#xff1b;JZC1-53中间继电器&#xff1b; JZC1-32中间继电器&#xff1b;JZC1-40中间继电器&#xff1b; JZC1-31中间…

HarmonyOS4.0从零开始的开发教程10Video组件的使用

HarmonyOS&#xff08;九&#xff09;Video组件的使用 概述 在手机、平板或是智慧屏这些终端设备上&#xff0c;媒体功能可以算作是我们最常用的场景之一。无论是实现音频的播放、录制、采集&#xff0c;还是视频的播放、切换、循环&#xff0c;亦或是相机的预览、拍照等功能…

【Python】翻译包translate

在Python里&#xff0c;可以用translate包完成语言的翻译转化 import translatetrantranslate.Translator(from_lang"ZH",to_lang"JA") strtran.translate("今天的天气怎么样")print(str)

四招打造完美分层自动化测试框架,让测试更高效!

写在前面 我们刚开始做自动化测试&#xff0c;可能写的代码都是基于原生写的代码&#xff0c;看起来特别不美观&#xff0c;而且感觉特别生硬。 来看下面一段代码&#xff1a; 具体表现如下&#xff1a; driver对象在测试类中显示 定位元素的value值在测试类中显示 定位元素…