Spring(Bean 作用域和生命周期)

news/2024/11/28 5:34:54/

目录

1. 案例1: Bean作用域的问题

2. 作用域

3. 设置 Bean 的作用域

4. Spring 的执行流程

5. Bean 的生命周期


1. 案例1: Bean作用域的问题

现在有一个公共的 Bean,通过给 A 用户 和 B 用户使用, 然后在使用的过程中 A 偷偷的修改了公共 Bean 的数据, 导致 B 在使用时发生了预期之外的逻辑错误

(1) 公共 Bean:   [名称是 java]

@Component
public class Users {@Beanpublic User user1() {User user = new User();user.setId(1);user.setName("java");return user;}
}

(2) A 用户使用时,进行了修改操作   [名称是 悟空, 进行了修改操作]

@Controller
public class BeanScopesController {@Autowiredprivate User user1;public User getUser1() {User user = user1;System.out.println("Bean 原 name: " + user.getName());user.setName("悟空");return user;}
}

(3) B 用户再去使用公共 Bean 的时候

@Controller
public class BeanScopesController2 {@Autowiredprivate User user1;public User getUser1() {User user = user1;return user;}
}

(4) 打印 A 用户和 B 用户公共 Bean 的值

public class BeanScopesTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");BeanScopesController beanScopesController = context.getBean(BeanScopesController.class);System.out.println("A 对象修改之后 Name: " + beanScopesController.getUser1().toString());BeanScopesController2 beanScopesController2 = context.getBean(BeanScopesController2.class);System.out.println("B 对象读取到是 Name: " + beanScopesController2.getUser1().toString());}
}

(5) 运行程序

(6) 原因分析 

存在这个问题的原因就是 Bean 默认情况下是 单例模式 (singleton), 也就是所有类使用的都是同一个对象, 使用同一个对象,那就是没有过多的生命周期的创建和销毁,从而可以提高性能,所以在 Spring 中 Bean 的作用域也是 单例模式的


2. 作用域

限定程序中变量的可用范围叫做作用域.

Bean的作用域是指, Bean 在 Spring 整个框架中的某种行为,比如 单例模式的作用域, 意思就是 Bean 在整个 Spring 中只有一份, 它是全局共享的, 当有人修改了这个值后, 其他人读到的就是被修改的值

Spring 容器在初始化一个 Bean 的实例时,会同时指定该实例的作用域,Spring中有 6 种作用域

  1. singleton: 单例模式 (默认,每次请求取的是同一个对象)
  2. prototype: 原型模式 (多例模式,每次请求创建一个新的对象)
  3. request: 请求作用域 (Spring MVC,每次请求创建一个对象)
  4. session: 会话作用域 (Spring MVC,在一个会话中共享一个对象)
  5. application: 全局作用域 (Spring MVC,所有人共用一个)
  6. websocket: HTTP WebSocket 作用域 (Spring WebSocket 项目中存在的一种)

3. 设置 Bean 的作用域

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

@Scope 标签既可以修饰方法,也可以修饰类, @Scope 有两种设置方式

  • 直接设置值: @Scope("prototype")
  • 类似于枚举的常量方式: @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Component
public class Users {@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)@Beanpublic User user1() {User user = new User();user.setId(1);user.setName("java");return user;}
}

还是 案例1中的代码,只不过加上 Bean的作用域 原型模式后,运行程序,可以看到A修改后,B没有受到影响


4. Spring 的执行流程

Spring 执行流程: 
  1. 启动 Spring 容器
  2. 实例化 Bean (分配内存空间)
  3. 将 Bean 注册到 Spring 中 (存操作)
  4. 将 Bean 装配到需要的类中 (取操作)


5. Bean 的生命周期

Bean 的生命周期:

  1. 实例化 Bean (给 Bean 分配内存空间)          买房子
  2. 设置属性 (Bean 对象注入)                            装修
  3. Bean 初始化                                                 买家电
  • 执行各种通知 (执行各种 Aware)
  • 执行初始化的前置方法
  • 执行构造方法,两种执行方式,一种是执行 @PostConstruct,另一种是执行 init-method
  • 执行初始化的后置方法

     4. 使用 Bean                                                    入住

     5. 销毁 Bean                                                    卖房

  • @PreDestroy (销毁前方法)
  • 重写 DisposableBean 接口方法
  • destroy-method
public class BeanLifeComponent implements BeanNameAware {@PostConstructpublic void postConstruct() {System.out.println("执行 PostConstruct()");}public void init() {System.out.println("执行 init-method");}public void use() {System.out.println("使用 bean");}@PreDestroypublic void preDestroy() {System.out.println("执行: preDestroy()");}public void setBeanName(String s) {System.out.println("执行了 Aware 通知");}
}
<?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.beans"></content:component-scan><beans><bean id="beanLifeComponent" class="com.beans.BeanLifeComponent" init-method="init"></bean></beans>
</beans>
public class BeanLifeTest {public static void main(String[] args) {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config2.xml");BeanLifeComponent lifeComponent = context.getBean(BeanLifeComponent.class);lifeComponent.use();//执行销毁方法context.destroy();}
}

先设置属性再进行初始化,作用是

如果先初始化,就会出现空引用了,所以了为了防止空引用,就要先设置属性注入,然后再进行初始化 


http://www.ppmy.cn/news/1698.html

相关文章

MATLAB算法实战应用案例精讲-【图像处理】目标检测(补充篇)(附实战案例及代码实现)

前言 本文为MATLAB算法实战应用案例精讲-【图像处理】目标检测(附实战案例及代码实现)的补充篇。 目标检测从2001年开始,在2012年成为分水岭,因为这一年基于深度学习的目标检测方法,逐渐使目标检测进入到快速发展的阶段,比较流行的算法可以分为两类,一类是基于Region …

分析常见限流算法及手写三种(计数器、漏斗、令牌桶)代码实现

常见的限流算法分析 限流在我们日常生活中经常见到&#xff0c;如火车站门口的栏杆、一些景点的门票只出售一定的数量 等等。在我们的开发中也用到了这种思想。 为什么要限流 在保证可用的情况下尽可能多增加进入的人数,其余的人在排队等待,或者返回友好提示,保证里面的进行…

MySQL-MHA高可用配置及故障切换

文章目录一、MHA概述二、MHA的组成1、MHA Node&#xff08;数据节点&#xff09;2、MHA Manager&#xff08;管理节点&#xff09;3、MHA 的特点四、搭建步骤实验思路实验操作故障模拟故障切换备选主库的算法一、MHA概述 MHA&#xff08;MasterHigh Availability&#xff09;是…

只要背着电脑,他可以去任何地方

12月是微软全球开发者月&#xff0c;MSDN 微软开发者社区将在此期间推出特别专栏《技术狂旅》&#xff0c;解读这些技术狂热爱好者的个人经历&#xff0c;循着他们的人生旅程看到我们自己的影子&#xff0c;希望能带给你一些启发或激励&#xff0c;一起探寻自身更多的可能性。 …

内网搭建在线文档服务

步骤 安装 Node 和 NPM;安装 git, gitbook,gitbook-cli;配置 Gitlab Webhook;创建 Webhook 监听服务;编辑文档检查实时更新;安装 Node,NPM 第一步我们先安装 Node 和 NPM, # 下载压缩包 wget https://nodejs.org/dist/v9.10.1/node-v9.10.1-linux-x64.tar.gz # 解压…

李峋同款会动的爱心Python代码版

最近看到不少关于李峋同款爱心的视频、文章,今天我们也分享一下李峋同款爱心 Python 代码版。要问李峋是谁?我也不太清楚,大家可自行百度,这个是我百度的结果,仅供参考。简单来说李峋同款爱心就是一个动态的♥型效果,主要 Python 代码实现如下:def build(self, number):…

HTML5期末考核大作业,网站——青岛民俗 7页。 美丽家乡 学生旅行 游玩 主题住宿网页

&#x1f468;‍&#x1f393;静态网站的编写主要是用 HTML DⅣV CSSJS等来完成页面的排版设计&#x1f469;‍&#x1f393;&#xff0c;一般的网页作业需要融入以下知识点&#xff1a;div布局、浮动定位、高级css、表格、表单及验证、js轮播图、音频视频Fash的应用、uli、下拉…

Almalinux 8 服务器初始化脚本

AlmaLinux centos 8 替代品 centos7 升级到 almalinux8 官方提供从centos7升级到almalinux8工具 AlmaLinux OS - 升级你的发行版 迁移CentOS 7到版本 8 的 AlmaLinux、Rocky Linux、Oracle Linux - Linux迷 (linuxmi.com) 从Centos-7迁移到AlmaLinux-8.6的教程_抽离1024的…