【Spring学习之生命周期】什么是生命周期?什么是作用域?了解六种作用域

news2024/11/26 9:41:59

前言:
💞💞从前⾯的课程我们可以看出 Spring 是⽤来读取和存储 Bean,因此在 Spring 中 Bean 是最核⼼的操作资源,所以接下来我们深⼊学习⼀下 Bean 对象。
前路漫漫,希望大家坚持下去,不忘初心,成为一名优秀的程序员

个人主页⭐: 书生♡
gitee主页🙋‍♂:奋斗的小白
专栏主页💞:JavaEE进阶专栏
博客领域💥:java编程前端,算法,强训题目
写作风格💞:超前知识点,干货,思路讲解,通俗易懂
支持博主💖:关注⭐,点赞、收藏⭐、留言💬

在这里插入图片描述

目录

  • 1.常见的作用域问题
    • 1.1 问题所在
    • 1.2 代码示例
  • 2. 作用域
    • 2.1 作用域定义
    • 2.2Bean 的 6 种作⽤域
      • 2.2.1 singleton 单例作⽤域
      • 2.2.2 prototype 原型作⽤域
      • 2.2.3request 请求作⽤域
      • 2.2.4 session 会话作⽤域
      • 2.2.5 application 全局作⽤域(了解)
      • 2.2.6 websocket :HTTP WebSocket 作⽤域
    • 2.3 singleton 和 application 的区别
    • 2.4 设置作用域
  • 3. Spring执行流程
  • 4.Bean ⽣命周期
    • 4.1Bean ⽣命周期
    • 4.2 实例化和初始化的区别
    • 4.3 Bean生命周期代码

1.常见的作用域问题

1.1 问题所在

 有一个公共类,类对象被@Controller注解修饰,里面的方法被方法注解@Bean修饰。现在有两个用户都使用这个公共类,但是其中一个用户突然改变了里面的值,这个就导致了另一个用户使用的时候变量值已经发生了变化,因此第二个用户得到的应该是修改以后的。

1.2 代码示例

公共类

@Controller
public class StudentBeans {

    @Bean
    public Student student1() {
        // 伪代码,构建对象
        Student stu = new Student();
        stu.setId(1);
        stu.setName("张三");
        stu.setAge(18);
        return stu;
    }
}

一个类

@Controller
public class UserController {

    @Resource(name = "user1")
    @Autowired
    //@Qualifier(value = "user2")
    private User user;

    public void getUser()
    {
        System.out.println("user:"+user);
        User user2=user;
        user2.setName("lisi");
        System.out.println("user:"+user2);
    }
}

另一个类

@Controller
public class User1Controller {

    @Autowired
    private User user;
    public void  getUser()
    {

        System.out.println("user:"+user);
    }
}

在这里插入图片描述
咋们看一下结果,会发现我们另一个类的消息也发生了变化,但是我们并没有改变第二各类的信息。
我们可以发现,我们只有在第一个类中,创建了一个局部的变量,将这个局部变量进行改变,但是为什么我们的公用的会发生变化呢?

 这里面就包含了我们本篇文章要讲述的作用域问题。

操作以上问题的原因是因为 Bean 默认情况下是单例状态(singleton),也就是所有⼈的使⽤的都是同
⼀个对象,这个就导致了,我们一个类改变了,那么就是公共类改变了。

这个时候就会由人问了?我在第一个类里面不是创建一个局部的User类型的变量吗?我改变的也是局部的,为啥会改变公共的呢?其实这个问题很简单,就是因为创建的 局部的User类型变量也是指向这个公共类的,所以哪怕直接改变的是非公共类,公共类也会改变的。这个大家不需要纠结。

之前我们学单例模式的时候都知道,使⽤单例可以很⼤程度上提⾼性能,所以在 Spring 中 Bean 的作⽤域默认也是 singleton单例模式。

下面我们正式进入我们今天要讲的内容。

2. 作用域

2.1 作用域定义

作用域:就是一个限制变量在程序的使用范围
或者说在源代码中定义变量的某个区域就叫做作⽤域

那Bean的作用域是什么呢?

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

2.2Bean 的 6 种作⽤域

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

Spring有 6 种作⽤域,最后四种是基于 Spring MVC ⽣效的,也就是说在普通的Spring项目中是见不到的,在普通的 Spring 项⽬中只有前两种。

  1. singleton:单例作⽤域(默认作用域)
  2. prototype:原型作⽤域(多例作⽤域)
  3. request:请求作⽤域
  4. session:回话作⽤域
  5. application:全局作⽤域
  6. websocket:HTTP WebSocket 作⽤域

2.2.1 singleton 单例作⽤域

描述:该作⽤域下的Bean在IoC容器中只存在⼀个实例:获取Bean(applicationContext.getBean获取)及装配Bean(@Autowired注⼊)都是同⼀个对象。

场景:通常⽆状态的Bean使⽤该作⽤域。⽆状态表示Bean对象的属性状态不需要更新

备注:Spring默认选择该作⽤域

2.2.2 prototype 原型作⽤域

描述:每次对该作⽤域下的Bean的请求都会创建新的实例:获取Bean( applicationContext.getBean获取)及装配Bean(@Autowired注⼊)都是新的对象 实例。

场景:通常有状态的Bean使⽤该作⽤域

2.2.3request 请求作⽤域

描述:每次前端发送http请求会创建新的Bean实例,类似于prototype

场景:⼀次http的请求和响应的共享Bean,等到第二次请求的时候,就会重新新建一个作用域

备注:限定SpringMVC中使⽤

2.2.4 session 会话作⽤域

描述:在⼀个http session中,定义⼀个Bean实例

场景:⽤户回话的共享Bean, ⽐如:记录⼀个⽤户的登陆信息

备注:限定SpringMVC中使⽤,session会话作用域的范围要比请求作用域更大

2.2.5 application 全局作⽤域(了解)

描述:在⼀个http servlet Context中,定义⼀个Bean实例

场景:Web应⽤的上下⽂信息,⽐如:记录⼀个应⽤的共享信息

备注:限定SpringMVC中使⽤

2.2.6 websocket :HTTP WebSocket 作⽤域

描述:在⼀个HTTP WebSocket的⽣命周期中,定义⼀个Bean实例

场景:WebSocket的每次会话中,保存了⼀个Map结构的头信息,将⽤来包裹客户端消息头。第⼀次初始化后,直到WebSocket结束都是同⼀个Bean。

备注:限定Spring WebSocket中使⽤

2.3 singleton 和 application 的区别

singleton 是 Spring Core 的作⽤域;application 是 Spring Web 中的作⽤域;

singleton 作⽤于 IoC 的容器,⽽ application 作⽤于 Servlet 容器。

2.4 设置作用域

我们的程序默认是单例作用域,这个就会导致,我们用的始终是一个Bean对象。会出现不是我们想要的结果,所以我们就要设置作用域。

使⽤ @Scope 标签就可以⽤来声明 Bean 的作⽤域

@Controller
public class UserBean {

    @Scope("prototype")//设置作用域
    @Bean
    public User user1()
    {
        User user=new User();
        user.setId(1);
        user.setName("张三");
        user.setPassword("123");
        return  user;
    }
}   

我们设置作用域有两种方式

一种是只直接设置作用域

@Scope(“prototype”)//设置作用域

另一种是使⽤成员变量设置

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)//设置作用域

两种都是可以设置作用域的

3. Spring执行流程

Spring流程分为四步:
第一步:启动容器(加载配置文件)
在这里插入图片描述
第二步:完成Bean初始化

这一步有两种方式:
1.使用xml直接注册bean
2.配置bean根(扫描)路径
在这里插入图片描述
第三步:注册bean对象到容器中(.将 bean存储到spring 中,通过类注解进行扫描和装配)
在这里插入图片描述
第四步:装配Bean属性 (将bean从spring读取出来,装配到相应的类)
在这里插入图片描述

Bean 执⾏流程(Spring 执⾏流程):启动 Spring 容器 -> 实例化 Bean(分配内存空间,从⽆到
有) -> Bean 注册到 Spring 中(存操作) -> 将 Bean 装配到需要的类中(取操作)。

4.Bean ⽣命周期

4.1Bean ⽣命周期

所谓的⽣命周期指的是⼀个对象从诞⽣到销毁的整个⽣命过程,我们把这个过程就叫做⼀个对象的⽣命周期。

Bean 的⽣命周期分为以下 5 ⼤部分:
1.实例化 Bean(为 Bean 分配内存空间,对应JVM中的加载)
2.设置属性(Bean 注⼊和装配)
3.Bean 初始化
  实现了各种 通知的⽅法,
  执⾏ 初始化前置⽅法;
  执⾏ 初始化⽅法,依赖注⼊操作之后被执⾏;执⾏⾃⼰指定的 init-method方法
  执⾏初始化后置⽅法。
4.使⽤ Bean
5.销毁 Bean

整个生命周期就好像我买了一个房子:
1.实例化就像是:买了一个毛坯房,
2.设置属性就等同于:购买装修材料(引入外部资源),
3.初始化就等同于:给房子装修,
 3.1里面的各种通知方法:相当于通知装修的工人
 3.2初始化前置工作:就相当于制定装修方法
 3.3进行初始化:就相当于工人师傅开始装修了
 3.4初始化的后置工作:相当于装修后的清理工作
4.使用Bean:就相当于入住房子
5.销毁房子:等同于卖掉房子

销毁容器的各种⽅法,如 @PreDestroy、DisposableBean 接⼝⽅法、destroy-method

4.2 实例化和初始化的区别

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

4.3 Bean生命周期代码

package Spring;

import Spring.demo.component.BeanLifeComponent;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App2 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        BeanLifeComponent life = context.getBean("beanLifeComponent",BeanLifeComponent.class);
        System.out.println(" 使用Bean⽅法");
        // 执⾏销毁⽅法
        context.destroy();
    }
}

package Spring.demo.component;

import org.springframework.beans.factory.BeanNameAware;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class BeanLifeComponent  implements BeanNameAware {
    @PostConstruct
    public void postConstruct() {
        System.out.println("执⾏ PostConstruct()");
    }
    public void init() {
        System.out.println("执⾏ BeanLifeComponent init-method");
    }

    public void setBeanName(String s) {
        System.out.println("执⾏了通知 ");
    }
    @PreDestroy
    public void preDestroy() {
        System.out.println("执⾏:preDestroy()");
    }
}

最重要的是配置spring-config.xml文件
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

让你不再疑惑如何转换音频格式

你是否曾经遇到过这样的问题?你有一些wav格式的音频文件,但是它们不能在你的设备上播放,或者你需要将它们转换为其他格式以便更好地编辑和分享。别担心,转换wav格式并不是一件麻烦的事情。如果你还不知道wav格式怎么转换的话&…

今天面了个阿里拿27K出来的测试,真是砂纸擦屁股,给我露了一手啊

2023年春招已经结束,很多小伙伴收获不错,拿到了心仪的 offer。 各大论坛和社区里也看见不少小伙伴慷慨地分享了常见的面试题和八股文,为此咱这里也统一做一次大整理和大归类,这也算是划重点了。 俗话说得好,他山之石…

如何判断测量所得的CSI是视距还是非视距

1、视距(LOS)传播 无线电波沿直线传播的方式称为视距传播。 2、非视距(NLOS)传播 当CSI接收机与基站(BS)之间的直射路径被障碍物挡住后,无线电波只能在经过反射和衍射后到达接收端,此时测量到的数据&…

由于找不到msvcp120.dll怎么办,msvcp120.dll一键修复方法

运行软件程序或游戏,提示由于找不到msvcp120.dll,遇到这种问题要怎么办呢?一般都是计算机系统的dll动态链接库损坏或者文件丢失,不用慌,这个只要修复一下就可以,下面小编就一一道来,还可以实现一…

PMP证书没过期的同学吃香了,直接对标CSPM国标证书二级

2021年10月,中共中央、国务院发布的《国家标准化发展纲要》明确提出构建多层次从业人员培养培训体系,开展专业人才培养培训和国家质量基础设施综合教育。建立健全人才的职业能力评价和激励机制。由中国标准化协会(CAS)组织开展的项…

使用dmhs veri手动比对ORACLE同步到DM数据

使用dmhs veri手动比对ORACLE同步到DM数据 veri介绍 在进行数据库数据的实时同步的时候,需要了解同步的结果是否正确,因此需要有数据对比工具进行数据的对比,并生成详细的对比报告,提供用户参考。对比工具仅仅生成报告&#xff…

【OpenMMLab】AI实战营第二期Day10:底层视觉与MMEditing

Summary 本课程包含底层视觉和MMEditing两个部分。第一部分介绍图像超分、深度学习和网络训练的相关算法,第二部分介绍超像素卷积、无监督学习、卷积网络和空间注意机制,以及这些算法在视觉框架中的实践应用。 Highlights 📷介绍计算机视觉…

ChatGPT 3.5/4 双双升级:更长,更便宜,更开放,更可控

OpenAI 今年早些时候发布了 gpt-3.5-turbo 和 gpt-4,并且在短短几个月内,开发者在这些模型上开发了很多令人印象深刻的应用。 6月13日, OpenAI 官宣了版本更新的内容: Chat Completions API 中新增了函数调用功能。更可控的 gpt-4…

【有奖体验】叮!你有一张 3D 卡通头像请查收

立即体验基于函数计算部署【图生图】一键部署 3D 卡通风格模型:https://developer.aliyun.com/topic/aigc_fc 人工智能生成内容(Artificial Intelligence Generated Content,简称 AIGC)是当下最火的概念之一。AIGC 被认为是继专业…

MFC .rc文件解析(EXE属性详细信息添加)

文章目录 Windows 资源文件(.rc文件)资源(Resources)类型从文件导入的(BITMAP,ICON,HTML,FONT,CURSOR 等)对话框资源类型:(DIALOG,DIALOGEX 等)菜单资源类型字…

【Java项目】使用Nacos实现动态线程池技术以及Nacos配置文件更新监听事件

文章目录 项目源码线程池概念ThreadPoolExecutor介绍Nacos实现对Nacos配置文件更新的事件监听机制定时通知功能邮件发送通知功能开始测试 项目源码 真诚的希望能给我项目一个stars!!! 项目源码 线程池概念 线程池(Thread Pool&…

Megatron-LM GPT2

内容 使用原始 Megatron-LM 训练 GPT-2 训练数据设置运行未修改的 Megatron-LM GPT2 模型启用 DeepSpeed 参数解析初始化和训练 初始化使用训练 API 前向传播反向传播更新模型参数损失缩放检查点保存和加载DeepSpeed 激活检查点(可选)训练脚本使用 GPT-…

拆分代码 + 预加载,减少首屏资源,提升首屏性能及应用体验

route-resource-preload 组件懒加载可以极大地提升我们的应用首屏加载体验, 但我们在进行组件资源拆包后,一旦加载某个组件资源出现以上时间过长的情况,则会出现视图无法正常渲染的问题(导致页面白屏/组件出不来/交互卡顿等情况)。…

Pytest教程__钩子方法setup、teardown、setup_class、teardown_class(8)

pytest跳过用例执行的用法与unittest跳过用例大致相同。 pytest跳过用例的方法如下: pytest.mark.skip(reason):无条件用例。reason是跳过原因,下同。pytest.mark.skipIf(condition, reason):condition为True时跳过用例。 pyte…

代码随想录算法训练营第五十八天|739. 每日温度|496.下一个更大元素 I

LeetCode739. 每日温度 基本思路:什么时候使用单调栈呢?通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。时间复杂度为O(n)。例如本题其实就是找找到一个元素右…

【发电厂】发电厂模型验证应用于电网事件在线性能监测【相量测量单元 (PMU) 数据对电网事件的在线性能监控】研究(MatlabSimulink实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

(一文详解!)wrk性能测试

目录 一、简介 二、格式及用法 三、简单压测及结果分析 四、使用lua脚本进行压测 一、简介 wrk 是一款针对 Http 协议的基准测试工具,它能够在单机多核 CPU 的条件下,使用系统自带的高性能 I/O 机制,如 epoll,kqueue 等&#xff0…

华为OD机试真题 JavaScript 实现【报数游戏】【2022Q4 100分】

一、题目描述 100个人围成一圈,每个人有一个编码,编号从1开始到100。他们从1开始依次报数,报到为M的人自动退出圈圈,然后下一个人接着从1开始报数,直到剩余的人数小于M。请问最后剩余的人在原先的编号为多少&#xff…

Ubuntu 更新 CMake 版本

项目中有时候会出现CMake版本小于最低要求的情况,实际上没有有必要这么高的要求,但是在不能改对方代码的情况下,只能去升级自身的版本了. 尝试了网上说的直接update之后再次安装的方式,结果版本号没有改变 sudo apt-get update sudo apt-get remove cmake sudo apt-get ins…

Rust语言从入门到入坑——(3)小谈Cargo工具以及VScode配置Rust

文章目录 0 引入1、Cargo 是什么2、常用Cargo指令3、VScode配置Rust环境3.1.tasks.json3.2.launch.json 4、总结 0 引入 上一节我们谈了在编译工程的时候用到Cargo(卡狗) 1、Cargo 是什么 Cargo 是 Rust 的构建系统和包管理器。 Rust 开发者常用 Carg…