Bean 作用域与生命周期

news2024/10/7 16:22:07

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 {
    @Bean
    public 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 {

    @Autowired
    private 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 {
    @Resource
    private 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) // 方式二
    @Bean
    public 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 {

    @Override
    public void setBeanName(String s) {
        System.out.println("执行:BeanNameAware setBeanName 方法:"+s);
    }

    // 初始化方式一:@PostConstruct
    @PostConstruct
    public void postConstruct() {
        System.out.println("执行了:@PostConstruct");
    }

    // 初始化方式二:init-method
    public void init(){
        System.out.println("执行了:init-method"); //要是用 xml 配置 <Beans>里面的标签
        
    }

    // 销毁方法一:
    @PreDestroy
    public 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.coloradmin.cn/o/767589.html

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

相关文章

【Java】Java实现微信小程序发送服务通知

文章目录 前言一、文档来源二、JAR包引入三、后端工作四、编写配置文件配置一&#xff1a;WxConfig配置二&#xff1a;WxProperties 五、代码编写 前言 在上个月接到一个需求&#xff0c;大概是需要计算一条数据的最大办理时间从而发送任务超期的微信小程序服务通知&#xff0…

怎么进行流程图制作?分享几种绘制方法

怎么进行流程图制作&#xff1f;流程图是一种图形化表示流程的图表&#xff0c;通常用于描述业务、计划或工作流程。它可以帮助人们更好地理解复杂的流程&#xff0c;并且提供了一种清晰的方法来记录和共享流程信息。下面介绍一些绘制流程图的方法&#xff0c;可以帮助我们快速…

4 自动微分 Automatic Differentitaion

计算图 Computational Graph 图上的每个节点代表一个中间值边事输入输出的关系 forward 求导 forward mode AD 上图中从前向后&#xff0c;一步一步计算每个中间值对 x1的偏导&#xff0c;那么计算到 v7&#xff0c;就得到了整个函数对于 x1的偏导。 有limitation 对一个参数…

echarts开发遇到的问题

echarts开发遇到的问题 1.rich富文本标签作为横向柱状图的刻度标签&#xff0c;其中带有icon。rich里不能写参数&#xff0c;只能写死&#xff1f;圆角设置无效&#xff1f; 解决办法&#xff1a; 自己写横向柱状图 散点图性能优化配置的临界点&#xff0c;最低优化数值必须…

超全整理,软件测试高频面试题(功能/接口/自动化测试-附答案)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 功能测试 1、双十…

LCD—STM32液晶显示(4.液晶控制代码讲解)

目录 STM32液晶控制代码讲解 液晶接口封装介绍 使用LCD的配置步骤 内存操作要使用volatile进行修饰 图形绘制实现 绘制矩形 重点补充 STM32液晶控制代码讲解 液晶接口封装介绍 指南者液晶接口原理图 左边DB00—DB15表示液晶屏的数据线引脚&#xff0c;分别对应STM32的F…

使用ppocr突然退出问题

本次使用conda装了一个cuda10.2版本的paddleocr&#xff0c;然后所有的环境检查没问题&#xff0c;使用paddle自带的检查代码&#xff0c;输出提醒paddle可以正常使用&#xff1a; >>> import paddle >>> paddle.utils.run_check() 输出结果提示安装正常 …

零编程经验也能打造精美微信展示小程序的秘诀揭秘

随着微信的普及和发展&#xff0c;微信展示小程序成为了许多企业展示自己形象的重要渠道。那么如何快速地搭建一个精美的微信展示小程序呢&#xff1f;下面就为大家详细介绍一下具体操作步骤。 首先&#xff0c;进入【乔拓云】平台后台。乔拓云是一款非常优秀的小程序开发平台&…

php伪协议(文件包含)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 php伪协议 伪协议详情 php伪协议 文件包含直接读取的是文件&#xff0c;而不是文件源码&#xff0c;所以要想办法读取源码方法。 那么就要涉及到 PHP 伪协议 ph…

LabVIEW开发航空电子设备嵌入式诊断半物理仿真系统

LabVIEW开发航空电子设备嵌入式诊断半物理仿真系统 航电集成系统是现代战争飞机的重要组成部分&#xff0c;包括惯性导航系统、飞行控制系统、机电管理系统和任务计算机等子系统。战机的作战性能与航电系统息息相关&#xff0c;可以说&#xff0c;没有高性能的空电系统&#x…

行业首家!法大大荣获“数据安全管理能力认证(DSMC)”证书

7月11日&#xff0c;法大大获得由中国信息通信研究院&#xff08;以下简称“中国信通院”&#xff09;颁发的“数据安全管理能力认证&#xff08;DSMC&#xff09;证书”&#xff08;以下简称“DSMC证书”&#xff09;&#xff0c;成为行业内首家获颁该证书的企业&#xff0c;法…

基于Java+SpringBoot+Vue前后端分离校园管理系统详细设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

Spring Cloud Alibaba【创建支付服务生产者、创建服务消费者 、Dubbo和OpenFeign区别 、微服务接入OpenFeign】(二)

目录 分布式服务治理_创建支付服务生产者 分布式服务治理_创建服务消费者 服务调用_Dubbo和OpenFeign区别 服务调用_微服务接入OpenFeign 分布式服务治理_创建支付服务生产者 创建服务提供者工程cloud-provider-payment8001 POM文件引入依赖 <dependencies><…

MP4怎么转换为gif的格式?快试试这两个方法!

想要将MP4视频文件转换为GIF格式&#xff1f;不用担心&#xff0c;本文将为您介绍两种简单易行的方法&#xff1a;记灵在线工具和使用FFmpeg命令行工具。这些方法适用于不同的用户&#xff0c;无论您是喜欢在线工具还是偏向命令行操作&#xff0c;都能找到适合自己的方式。让我…

开源代码分享(8)—大规模电动汽车时空耦合双层优化调度(附matlab代码)

参考文献&#xff1a; [1]He L , Yang J , Yan J , et al. A bi-layer optimization based temporal and spatial scheduling for large-scale electric vehicles[J]. Applied Energy, 2016, 168(apr.15):179-192. DOI:10.1016/j.apenergy.2016.01.089 1.基本原理 1.1摘要 电…

Python模块基础

一、模块 模块可以看成是一堆函数的集合体。 一个py文件内部就可以放一堆函数&#xff0c;因此一个py文件就可以看成一个模块。 如果这个py文件的文件名为module.py&#xff0c;模块名则是module。 1、模块的四种形式 在Python中&#xff0c;总共有以下四种形式的模块&…

MySQL约束和查询

约束和查询 1. 约束1.1 约束类型1.2 常用的约束 2. 查询2.1 聚合查询2.1.1 聚合函数2.1.2 GROUP BY2.1.3 HAVING 2.2 联合查询2.2.1 内连接2.2.2 外连接 2.3 合并查询 1. 约束 1.1 约束类型 NOT NULL - 指示某列不能存储 NULL 值。UNIQUE - 保证某列的每行必须有唯一的值。DE…

TCP四次挥手过程

TCP 断开连接是通过四次挥手方式。 双方都可以主动断开连接&#xff0c;断开连接后主机中的「资源」将被释放&#xff0c; 刚开始双方都处于 establised 状态&#xff0c;假如是客户端先发起关闭请求&#xff0c;过程如下图&#xff1a; 第一次挥手&#xff1a;客户端打算关闭…

C++模拟实现位图和布隆过滤器(哈希)

目录 前言引入&#xff1a; 一、位图 1.1 位图概念 1.2 位图的实现 1.3 位图的应用 二、布隆过滤器 2.1 哈希的弊端 2.2 布隆过滤器概念 2.3 布隆过滤器的插入 2.4 布隆过滤器的查找 2.5 布隆过滤器的删除 2.6 布隆过滤器的模拟实现 2.7 布隆过滤器优缺点 三、…

CSS ::file-selector-button伪元素修改input上传文件按钮的样式

默认样式 修改后的样式 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdev…