【JavaEE】深入了解Spring中Bean的可见范围(作用域)以及前世今生(生命周期)
【JavaEE】Spring的开发要点总结(4)
文章目录
- 【JavaEE】Spring的开发要点总结(4)
- 1. Bean的作用域
- 1.1 一个例子感受作用域的存在
- 1.2 通过例子说明作用域的定义
- 1.3 六种不同的作用域
- 1.3.1 singleton单例模式(默认作用域)
- 1.3.2 prototype原型模式
- 1.3.3 request请求作用域
- 1.3.4 session会话作用域
- 1.3.5 application全局/应用作用域
- 1.3.6 "websocket" HTTP WebSocket作用域
- 1.4 设置Bean的作用域
- 2. Bean的生命周期
- 2.1 Spring的执行流程
- 2.2 Spring 的生命周期
- 2.3 Bean的生命周期
- 2.3.1 Bean初始化
- 2.3.2 Bean生命周期代码演示
- 2.3.3 为什么属性设置比Bean初始化早
【JavaEE】Spring的开发要点总结(4)
在学习Spring中,Bean是最核心的操作资源
- 使用学习Bean对象是一个重点,我们已经知道如何存储它,获取它,现在我们要知道:
- 它的作用域,我们才可以知道怎么使用,才能得心应手,符合预期~
- 它的生命周期,我们才能更加清楚的了解它的“生与死”,即程序执行的过程~
1. Bean的作用域
在学习C语言或者JavaSE的时候,熟悉一个变量的作用域非常重要,否则会出现很多错误,并且违背一些设计上的初心~
- C语言
- 全局变量,整个源文件可以访问,代码从上到下执行,局部优先,隔着源文件需要extern…
- 局部变量,在代码块中生效,在方法中生效,代码从上到下执行
- 静态变量,局部变量的作用域,全局变量的生命周期~
- Java
- 修饰访问限定符
- 局部变量…
- 成员变量,静态成员变量…
知己知彼,才能百战百胜~
1.1 一个例子感受作用域的存在
之前的代码,我们只是一个简单的读操作,没有涉及其他,所以作用域感受不明显,接下来一个例子说明一下~
背景故事:
一个公司开发了一个外卖平台,这个公司打算将这个平台卖给别的公司,赚收成和维护费,但是每个公司都有特定的要求,而员工三人(小马、大马、老马),负责这个项目,小马负责公司原本的代码,大马负责A公司的外卖平台的代码,老马则负责B公司。
大马和老马的工作就是,对一些功能进行删减,添加个别的功能~
三人各自完成各自的业务~
所以就会如下的项目结构(实际情况要比这复杂很多,这个例子只是为了演示罢了):
- 小马代表UserController
- 大马代表UserController1
- 老马代表UserController2
这个Users类,就是一些原始的User的诞生和定义的地方~
- 这个类是一个公共类
- 这不代表这个里面诞生的对象就是公共的,而是存储Bean对象的手段是公共的
那么可能就会有以下场景:
再每次设置后都打印一次:
System.out.println(user2);
他们原本的意思就是,他们从spring中获取一个Bean对象(用户),设置对应的属性,为自己所用~
现在我们来测试一下:
@Component
public class Test {@Autowiredprivate UserController userController;@Autowiredprivate UserController1 userController1;@Autowiredprivate UserController2 userController2;public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");Test test = context.getBean("test", Test.class);test.userController.doMethod();test.userController1.doMethod();test.userController2.doMethod();}
}
从结果可以看出,下一次的更新,是在前一次更新的基础上进行的!
- 而小马大马老马三个人的操作都没有问题,他们都不知道对方进行修改了 ~
所以可以说明,他们用的Bean,是同一个!就像C语言全局变量那样~
这就是作用域中的一种:单例Bean对象
- 这里的单例跟我们之前的单例不一样,之前的单例是那个类的实例只有一个
- 而这里的单例是,这个Bean对象的实例只有一个
- 也就是说这个类型的Bean对象,名字为这个名字的Bean对象,有且只有一个~
改变Bean对象的作用域也很简单,只需要一个注解@Scope(意思就是作用域)~
默认情况下就是:singleton
我们如果要让小马大马老马获得的Bean对象都不一样,可以设置为:
prototype(原型/多例)
- 原型 => 每次获取该 Bean对象,都是重新获取初始的那一个
- 多例 => 这个类型这个名字的 Bean对象,有多个存在!
- 从结果可以看出,作用域的改变!
1.2 通过例子说明作用域的定义
Bean的作用域指的就是Bean对象在Spring整个框架中的某种行为模式:
- 比如singleton,单例模式,就表示这个Bean对象在整个Spring容器中只有一份,它是全局共享的,那么当其他人修改这个值之后,另一个人读取到的就是修改后的值
- 再比如prototype,原型模式,就表示这个Bean对象在整个Spring中可以存在多份,并且每次DI的时候,都是崭新的一个Bean对象,不同人获得的Bean是不一样的
- 所以prototype模式下的Bean对象的作用域就是:需要注入这个Bean的那个类的一个实例内部
- 类比两个不同的方法中定义的同一类型同一名字的变量~
1.3 六种不同的作用域
- singleton:单例作用域
- prototype:原型作用域
- request:请求作用域
- session:会话作用域
- application:全局作用域
- websocket:HTTP WebSocket作用域
Spring普通项目( Spring Core)其实就前面两种:singleton 和 prototype
后四种值则是在 Spring MVC 项目中的值
1.3.1 singleton单例模式(默认作用域)
单例模式的效率比较高(性能好)
- 只有第一次去加载它
经典的面试题:单例模式的Bean是线程安全的吗?
不是线程安全的~
- 所有人共同操作的变量,一定不是线程安全的
解决方案:使用ThreadLocal(本地线程变量)
- 这是解决线程安全的其中一种方式!
文章推荐:ThreadLocal不好用?那是你没用对!| Java Debug 笔记 - 掘金 (juejin.cn)
ThreadLocal的基础方法:
- set方法
- get方法
- remove方法
可能存太多没有remove,内存溢出的问题也会出现,感兴趣的可以去了解一下
相比于使用锁来解决线程安全问题
- 使用ThreadLocal可能会导致结果与锁不一致的情况
- 特别是在多个线程之间存在依赖关系的情况下。
- 因为每个线程都有自己的数据副本,如果线程之间需要共享数据并进行协作,那么就需要额外的协调机制来保证数据的一致性。
- 否则,可能会出现一个线程修改了数据,但其他线程并不知道的情况,导致结果不一致。
所以在使用ThreadLocal解决线程安全问题时,**需要根据具体的业务场景来评估是否适合使用ThreadLocal,**并确保线程之间的数据协作和一致性。
对于一些依赖全局状态的场景,使用锁可能更适合。
1.3.2 prototype原型模式
每次获取(DI)的都是一个原型的对象:
1.3.3 request请求作用域
顾名思义,在每一次HTTP请求的时候,创建一次原型,与prototype类似
在一次HTTP请求和响应中,共享Bean
注意:限定在Spring MVC中使用
因为Spring Core项目不支持HTTP
Spring MVC项目也叫作 Spring Web项目,支持HTTP
1.3.4 session会话作用域
顾名思义,一个HTTP Session中,共享Bean
- 例如记录一个用户的登录信息,同一个session,每次获取Bean的时候不要原型
注意:限定在Spring MVC中使用
后面四种可能会比较难理解,这是因为我们还没有接触Spring MVC,所以不太了解具体用法!
- 之后的实践肯定会对这些知识更加清晰!
1.3.5 application全局/应用作用域
在一个http servlet Context中,共享Bean
即一个Context容器,共享Bean
- web应用的上下文信息,例如记录一个应用的共享信息
注意:限定在Spring MVC中使用
对于普通的Spring项目是不能用这个值的
但是对于singleton单例模式,Bean的作用域不超过一个ApplicationContext对象(一个context是一个容器,不同context进行各自的注入…):
singleton和application有什么区别呢?
- 前者是Spring Core的全局作用域,作用于IoC容器
- 后者是Spring MVC(Spring Web)的全局作用域,作用于Servlet容器
了解即可
1.3.6 “websocket” HTTP WebSocket作用域
在一个HTTP WebSocket的生命周期中,共享Bean
就是一个特殊项目里使用的特殊值罢了
注意:限定在Spring WebSocket中使用
WebSocket的每次会话中,保存了一个Map结构的头信息,将用来包裹客户端消息头。第一次初始化后,直到WebSocket结束都是同一个Bean。
如果对WebSocket项目感兴趣的同学可以去学习,如果不感兴趣,了解一下也可以
1.4 设置Bean的作用域
- 直接设置
- @scope(“prototype”)
- 利用全局变量
- 不用记忆单词,借助题词
- 不用记忆单词,借助题词
效果一致~
对于 & :了解即可!
2. Bean的生命周期
2.1 Spring的执行流程
笼统的流程:
- 回答问题的时候,不用讲太细致~
- 启动容器
-
加载配置文件(根据参数)
-
完成Bean的实例化(根据提供的扫描路径,找五大类注解)
- 这样Bean对象就成型了,但是是游离在内存中
- 这样Bean对象就成型了,但是是游离在内存中
-
注册Bean对象到容器中
- 装配Bean的属性(DI)
6.……
2.2 Spring 的生命周期
跟流程基本一致(粗糙的了解):
- 启动容器
- 读取配置进行Bean实例化
- 将Bean加入到容器中
- 装配Bean属性(给当前类的属性进行赋值,DI)
- 运行业务代码
- 销毁Bean
- 关闭容器
2.3 Bean的生命周期
所谓的生命周期指的是一个对象从诞生到销毁的整个生命周期,我们把这个过程叫做一个对象的生命周期
Spring的一生其实也差不多是Bean 的一生吧~
Bean的生命周期,也是经典的面试题!
- 这一部分讲的就比较细致,但是也是了解为主~
Bean的生命周期分为以下5大部分:
- 实例化Bean
- 只是分配内存空间,现在Bean既没有初始化,而且还是游离在内存中的
- 设置属性
- 进行依赖注入,将需要的但没有初始化的Bean对象注入到属性中,Bean不游离了
- Bean初始化
- 流程较多,大概就是对Bean进行一系列的操作,然后Bean里面的值是有意义的
- 其中就可能涉及Bean注入的属性
- 使用Bean
- 销毁Bean
2.3.1 Bean初始化
- 进行各种通知:如BeanNameAware、BeanFactoryAware…的接口方法
- 就是暴露一个判断而已,就是告知你Bean的名字设置好了…
- 至于你知道了这个通知后,进行什么逻辑就看你了~
- 而系统也会自动去干一些事情~
- 初始化前置方法(前戏,准备)
- 执行初始化方法(设置就一定会执行,不设置就不会执行)
- 注解的方式:@PostConstruct
- xml的方式:init-method方法
- 初始化后置方法
- 进行一些额外的操作和设置,以确保Bean在使用之前处于正确的状态
- xml的方式:destroy-method的值
- 注解的方式:@PreDestroy
2.3.2 Bean生命周期代码演示
- 以这个实行了BeanNameAware接口的类为例
如图是注解的方式去定义初始化方法
如图是xml的方式去决定使用什么初始化方法
- init-method的值对应的就是方法名,并且必须存在!
用注解设置多个初始化方法也更加方便~
- 这是用注解的方式设置销毁Bean的方法
- 这是用xml的方式设置销毁Bean的方法
对于初始化和销毁方法的设置,还有很多其他的方法!
- 但是注解就是香!
- xml的方式一次就一个
测试:
用子类,有更多的方法
获取Bean,使用Bean
扫描路径不要删掉,即使没用也要设置的
效果:
注解的优先级比较高~
顺序正如我们所料~
2.3.3 为什么属性设置比Bean初始化早
其实这个很容易想,例如一下操作:
如果user这个没有指向一块内存空间,只是null,那么就会空指针异常~
而实例化和属性注入之后,相当于在这里放了个箱子,之后的操作有了对象
文章到此结束!谢谢观看
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭🦆!Spring Core普通项目的讲解告一段落,接下来是Spring Boot的学习,敬请期待!
代码位置:SpringDemo4/src/main/java · 游离态/马拉圈2023年8月 - 码云 - 开源中国 (gitee.com)
相关文章:

【JavaEE】深入了解Spring中Bean的可见范围(作用域)以及前世今生(生命周期)
【JavaEE】Spring的开发要点总结(4) 文章目录 【JavaEE】Spring的开发要点总结(4)1. Bean的作用域1.1 一个例子感受作用域的存在1.2 通过例子说明作用域的定义1.3 六种不同的作用域1.3.1 singleton单例模式(默认作用域…...
P1320 压缩技术(续集版)
题目描述 设某汉字由 N N N \times N NN 的 0 \texttt 0 0 和 1 \texttt 1 1 的点阵图案组成。 我们依照以下规则生成压缩码。连续一组数值:从汉字点阵图案的第一行第一个符号开始计算,按书写顺序从左到右,由上至下。第一个数表示连续有…...

k8s(七) 叩丁狼 service Ingress
负责东西流量(同层级/内部服务网络通信)的通信 service的定义 apiVersion: v1 kind: Service metadata:name: nginx-svclabels:app: nginx-svc spec:ports:- name: http # service 端口配置的名称protocol: TCP # 端口绑定的协议,支持 TCP、…...

Android Studio 关于BottomNavigationView 无法预览视图我的解决办法
一、前言:最近在尝试一步一步开发一个自己的软件,刚开始遇到的问题就是当我们引用 com.google.android.material.bottomnavigation.BottomNavigationView出现了无法预览视图的现象,我也在网上查了很多中解决方法,最后在执行了如下…...

【STM32】小电流FOC驱控一体板(开源)
FOC驱控一体板 主控芯片stm32f103c8t6 驱动芯片drv8313 三相电流采样 根据B站一个UP主的改的(【【自制】年轻人的第一块FOC驱动器】),大多数元器件是0805,实验室具备且便于自己动手焊接 。 晶振用的是无源晶振,体…...

代码分析:循环创建N个子进程——为什么最后一个属于父进程?
黑马C/C 2018年32期代码分析 //循环创建n个子进程 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h>int main() {int i 0;for(i0; i<3; i){//创建子进程pid_t pid fork();if(pid&…...
【SpringBoot面试题整理-超级有效】
文章目录 1.SpringBoot如何解决跨域问题?2.为什么要用Spring Boot?3. Spring Boot的约定优于配置,你的理解是什么?4. SpringBoot有哪些优点?5. Spring Boot中自动装配机制的原理?6.SpringBoot支持哪些日志框…...

岩土工程仪器多通道振弦传感器信号转换器应用于隧道安全监测
岩土工程仪器多通道振弦传感器信号转换器应用于隧道安全监测 多通道振弦传感器信号转换器VTI104_DIN 是轨道安装式振弦传感器信号转换器,可将振弦、温度传感器信号转换为 RS485 数字信号和模拟信号输出,方便的接入已有监测系统。 传感器状态 专用指示灯方…...

西瓜书读书笔记整理(五)—— 第四章 决策树
第四章 决策树 4.1 基本流程4.1.1 什么是决策树算法4.1.2 决策树学习的目的4.1.3 决策树学习基本过程4.1.4 决策树学习基本算法4.1.5 递归结束的三种情况 4.2 划分选择4.2.1 信息增益(information gain)—— ID3 决策树学习算法属性划分准则4.2.2 信息增…...

STM32 4G学习
硬件连接 ATK-IDM750C模块可直接与正点原子 MiniSTM32F103开发板板载的ATK模块接口(ATK-MODULE)进行连接。 功能说明 ATK-IDM750C是正点原子(ALIENTEK)团队开发的一款高性能4G Cat1 DTU产品,支持移动4G、联通4G和…...
Golang 中实现实时聊天通讯
客户端代码 package mainimport ("fmt""log""net/url""os""os/signal""time""github.com/gorilla/websocket" )func main() {interrupt : make(chan os.Signal, 1)signal.Notify(interrupt, os.Interr…...
前端面试的性能优化部分(5)每天10个小知识点
目录 系列文章目录前端面试的性能优化部分(1)每天10个小知识点前端面试的性能优化部分(2)每天10个小知识点前端面试的性能优化部分(3)每天10个小知识点前端面试的性能优化部分(4)每天…...

【链表OJ 1】移除链表元素val
大家好,欢迎来到我的博客,此题是关于链表oj的第一题,此后还会陆续更新博客,如有错误,欢迎大家指正。 来源:https://leetcode.cn/problems/remove-linked-list-elements/description/ 题目: 方法一:定义prev和cur指针…...

复原 IP 地址——力扣93
文章目录 题目描述回溯题目描述 回溯 class Solution{public:static constexpr int seg_count=4<...

OSPF综合实验
实验题目如下: 实验拓扑如下: 实验要求如下: 【1】R4为ISP,其上只能配置IP地址: R4与其他所有直连设备间使用公有 【2】R3---R5/6/7为MGRE环境,R3为中心站点 【3】整个OSPF环境IP地址为172.16.0.0/16 【4】所有设备…...

安卓4G核心板开发板_MTK6785/MT6785(Helio G95)安卓手机主板方案
联发科MTK6785(Helio G95)安卓核心板采用八核 CPU 具有两个强大的 Arm Cortex-A76 处理器内核,主频高达 2.05GHz,外加六个 Cortex-A55 高效处理器。其强大的图形性能由 Arm Mali-G76 MC4 提供,速度可提升至 900MHz 。 …...

Linux 匿名页的生命周期
目录 匿名页的生成 匿名页生成时的状态 do_anonymous_page缺页中断源码 从匿名页加入Inactive lru引出 一个非常重要内核patch 匿名页何时回收 本文以Linux5.9源码讲述 匿名页的生成 用户空间malloc/mmap(非映射文件时)来分配内存,在内核空间发生…...

设计模式概述与UML图
文章目录 一、设计模式概述1. 软件设计模式的产生背景2. 软件设计模式的概念3. 学习设计模式的必要性4. 设计模式分类(1)创建型模式(2)结构型模式(3)行为型模式 二、UML图1. 类图概述2. 类图作用3. 类图表示…...

使用Vscode编辑keil工程
一、需要安装的插件 1. Keil Assistant 2. C/C 3. 中文配置: 二、插件配置 1. Keil Assistant 添加Keil的安装路径 接下来就可以使用vscode编辑Keil的工程了,调试编译和下载程序需要返回到Keil中进行操作。 三、Vscode常用快捷键 可以自定义进行配置…...

编译工具:CMake(一) | 简介与安装
编译工具:CMake(一) | 简介与安装 1. CMake简介1.1CMake的特点 2. CMake 安装 这个是CMake的图标 1. CMake简介 cmake 是 kitware 公司以及一些开源开发者在开发几个工具套件(VTK)的过程中衍生品,最终形成体系,成为一…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...

mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...