当前位置: 首页 > news >正文

【Spring Boot】Spring 魔法世界:Bean 作用域与生命周期的奇妙之旅

前言

???本期讲解关于spring原理Bean的相关知识介绍~~~

??感兴趣的小伙伴看一看小编主页:-CSDN博客

?? 你的点赞就是小编不断更新的最大动力

??那么废话不多说直接开整吧~~

目录

???1.Bean的作用域

??1.1概念

??1.2Bean的作用域

??1.3代码演示

???2.Bean的生命周期

??2.1概念以及分类

??2.2代码演示

??2.3原码阅读

2.3.1解析Bean类

2.3.2实例化前处理

2.3.3创建Bean的实例

2.3.4初始化Bean

???3.总结

**??**1.Bean的作用域

??1.1概念

在Spring IoC&DI阶段, 我们学习了Spring是如何帮助我们管理对象的.

1. 通过 @Controller , @Service , @Repository , @Component , @Configuration ,@Bean 来声明Bean对象.

2. 通过 ApplicationContext 或者 BeanFactory 来获取对象

3. 通过 @Autowired , Setter 法或者构造法等来为应程序注所依赖的Bean对象

如下代码所示:

首先我们在model层定义一个实体类:

public class Dog {public String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}

然后我们在config层通过@Bean将对象交给spring帮我们进行管理:

@Configuration
public class DogBeanConfig {//使用@Bean将对象交给spring进行管理@Beanpublic Dog dog(){Dog dog = new Dog();dog.setName("wangcai");return dog;}
}

那么在后面我们可以从spring容器中获取得到这里对象;

@SpringBootTest
class SpringPrincipleApplicationTests {@AutowiredApplicationContext context;@Testvoid contextLoads() {//单列模式Dog dog = context.getBean("dog", Dog.class);System.out.println(dog);}}

当然这小编是在test包中进行测试使用的,所以需要注入applicationcontext类,获取spring上下文(获取spring容器),再拿到这里对象;

此时我们再次拿对象,然后进行两次对象获取打印对应的地址发现:

地址是一样的, 说明每次从Spring容器中取出来的对象都是同个.这也是"单例模式"

单例模式: 确保个类只有个实例,多次创建也不会创建出多个实例
默认情况下, Spring容器中的bean都是单例的, 这种为模式, 我们就称之为Bean的作域

所以bean的作用域概念就是:

Bean的作用域是指在spring框架中一种行为模式

单例作用域表示全局只有一份,他是全局共享的,若进行了修改,那么再次获取次对象的某个属性就是被修改过后的属性;

但是如何再次访问时,如何重新创建一个对象呢,那么这就是其他的作用域了;

??1.2Bean的作用域

Bean的作用域分为6种,如下所示:

1. singleton:单例作域

2. prototype:原型作域(多例作域)
3. request:请求作域
4. session:会话作域
5. Application: 全局作域
6. websocket:HTTP WebSocket 作域

这六种作用域的大致作用意义如下表所示:

Bean的6种作用域

singleton

每个Spring IoC容器内同名称的bean只有个实例(单例)(默认

prototype

每次使该bean时会创建新的实例(单例)

request

每个HTTP 请求命周期内, 创建新的实例

session

每个HTTP Session命周期内, 创建新的实例

Application

每个ServletContext命周期内, 创建新的实例

websocket

每个WebSocket命周期内, 创建新的实例

??1.3代码演示

以下就是代码演示:

@Configuration
public class DogBeanConfig {//使用@Bean将对象交给spring进行管理@Beanpublic Dog dog(){Dog dog = new Dog();dog.setName("wangcai");return dog;}@Bean@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)public Dog singletonDog(){Dog dog =new Dog();return dog;}//原型作用域@Bean@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)public Dog prototypeDog(){Dog dog =new Dog();return dog;}//请求作用域@Bean@RequestScopepublic Dog requestDog(){Dog dog =new Dog();return dog;}//会话作用域@Bean@SessionScopepublic Dog sessionDog(){Dog dog =new Dog();return dog;}@Bean@ApplicationScopepublic Dog applicationDog(){Dog dog =new Dog();return dog;}
}

其中单列作用域,与多列作用域(原型作用域)使用@scope注解,其余作用域使用对应名字的注解,内部等于

@Scope(value =WebApplicationContext.SCOPE_REQUEST, proxyMode =
ScopedProxyMode.TARGET_CLASS)

其中黄色标注部分是可以进行对应作用域的更改的;其中 proxyMode为spring bean设置代理,表示bean是基于CGLIB进行动态代理的;

测试代码如下所示:

@RestController
@RequestMapping("/test")
public class DogBeanController {@Autowiredprivate ApplicationContext context;@Autowiredprivate Dog singletonDog;@Autowiredprivate Dog prototypeDog;@Autowiredprivate Dog requestDog;@Autowiredprivate Dog sessionDog;@Autowiredprivate Dog applicationDog;/*** 通过比较不同作用域,spring容器启动直接注入,后不会进行改变(原型作用域)* @return*/@RequestMapping("/single")public String single(){//从context获取对象Dog contexDog = context.getBean("singletonDog",Dog.class);return "contextDog:"+contexDog +",autowiredDog:"+singletonDog;}@RequestMapping("/prototype")public String prototype(){//从context获取对象Dog contexDog = context.getBean("prototypeDog",Dog.class);return "contextDog:"+contexDog +",<br/> autowiredDog:"+prototypeDog;}@RequestMapping("/request")public String request(){//从context获取对象Dog contexDog = context.getBean("requestDog",Dog.class);return "contextDog:"+contexDog +",<br/> autowiredDog:"+requestDog;}@RequestMapping("/session")public String session(){//从context获取对象Dog contexDog = context.getBean("sessionDog",Dog.class);return "contextDog:"+contexDog +",<br/> autowiredDog:"+sessionDog;}@RequestMapping("/application")public String application(){//从context获取对象Dog contexDog = context.getBean("applicationDog",Dog.class);return "contextDog:"+contexDog +",<br/> autowiredDog:"+applicationDog;}
}

这里需要注意的是,autowired直接注入是在spring容器启动时就进行注入,Applicationcontext获取容器注入是每次请求才注入对象;

所以具体的请求情况如下所示:

对于单列来说,对象是共享的,所以注入的对象地址两个都是一样的;

对于原型作用域:

由于每次请求使用bean时都会创建新的实例,所以多次请求会进行变化,spring启动时就已经注入,所以不会进行变化(除非重启服务);

对于请求作用域:

因为每次请求都会重新创建实例,所以不断刷新后对象地址就会进行改变;

对于会话作用域:

对于会话作用域,范围比请求作用域更加广泛,在一个浏览器上算是一个会话,如果要进行改变对象地址,就得重新开启一个会话,那么可以使用两个浏览器进行url的请求访问,那么此时不同浏览器的对象地址就是不一样的;

最后一个应用作用域,小编就不再进行演示了,结果和单例一样;

Application scope就是对于整个web容器来说, bean的作域是ServletContext级别的. 这个和
singleton有点类似,区别在于: Application scope是ServletContext的单例, singleton是个
ApplicationContext的单例. 在个web容器中ApplicationContext可以有多个

**??**2.Bean的生命周期

??2.1概念以及分类

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

Bean 的命周期分为以下5个部分:
1. 实例化(为Bean分配内存空间)

2. 属性赋值(Bean注和装配, 如 @AutoWired )

3. 初始化
a. 执各种通知, 如 BeanNameAware , BeanFactoryAware ,ApplicationContextAware 的接口方法.
b. 执初始化法
xml定义 init-method
使注解的式 @PostConstruct
执初始化后置法( BeanPostProcessor )

4. 使Bean

5. 销毁Bean

??2.2代码演示

代码如下所示:

@Component
public class BeanLifeComponent implements BeanNameAware {public Dog singletonDog;public BeanLifeComponent() {System.out.println("执行构造函数...");}//属性注入@Autowiredpublic void setSingletonDog(Dog singletonDog) {this.singletonDog = singletonDog;System.out.println("执行setSingletonDog....");}//执行各种通知@Overridepublic void setBeanName(String name) {System.out.println("setBeanName: "+name);}//初始化方法@PostConstructpublic void init(){System.out.println("执行PostConstruct...");}//使用beanpublic void use(){System.out.println("执行use方法....");}//销毁bean@PreDestroypublic void destroy(){System.out.println("执行destroy方法");}
}

对应就是,实例化分配内存,然后属性注入,在进行初始化(各种通知,以及通过注解初始化方法,最后使用bean,以及销毁bean)

日志打印如下:

??2.3原码阅读

首先点击进入AbstractAutowireCapableBeanFactory类查看源码内容:

找到AbstractAutowireCapableBeanFactory类里createBean方法的实现

此方法主要在创建过程中,会先进行一些准备工作,比如解析 Bean 的类,还会尝试在实例化之前进行一些处理,若有合适的处理器处理并返回了 Bean 实例,就直接返回;若没有,则调用doCreateBean方法实际创建 Bean 实例。

2.3.1解析Bean类
 Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);

this.resolveBeanClass(mbd, beanName, new Class[0]):尝试解析 Bean 定义对应的类。若解析成功,且 Bean 定义里没有直接设置类,同时 Bean 类名不为空,就创建一个新的 RootBeanDefinition 对象 mbdToUse,并把解析后的类设置进去。
qwqw

2.3.2实例化前处理
       try {beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);if (beanInstance != null) {return beanInstance;}

这里的resolveBeforeInstantiation会调用后至处理器的方法,在执行后,判断如果该实例为非空的,那么直接返回这个实例,不再执行下面实例化的创建过程;

2.3.3创建Bean的实例

在上述解析和实例化处理后,就开始执行实例的创建工作了,主要的方法就是doBeanCreate;

        try {beanInstance = this.doCreateBean(beanName, mbdToUse, args);if (this.logger.isTraceEnabled()) {this.logger.trace("Finished creating instance of bean '" + beanName + "'");}return beanInstance;

this.doCreateBean(beanName, mbdToUse, args):调用该方法实际创建 Bean 实例,这个方法包含了实例化、属性注入、初始化等一系列操作。

点开doCreateBean方法;

在此方法中:

这三个法与三个命周期阶段对应
1. createBeanInstance() -> 实例化
2. populateBean() -> 属性赋值
3. initializeBean() -> 初始化

点击进入initializeBean();

2.3.4初始化Bean

initializeBean 方法的主要作用是对已经实例化的 Bean 进行初始化操作,包括调用 Aware 接口方法、应用 BeanPostProcessor 前置处理、调用初始化方法以及应用 BeanPostProcessor 后置处理。这里可以对照英文单词看看;

其中初始化方法如下:

invokeAwareMethods 方法用于检查 Bean 是否实现了特定的 Aware 接口,若实现了就判断是否实现了特定的子接口;例如实现了BeanNameAware接口,调用相应的 setter 方法,将相关信息注入到 Bean 中。

大致的思维导图就是:

**??**3.总结

本期主要讲解了Spring原理中的Bean的作用域以及生命周期,通过概念以及相关代码进行演示,最后深入源码讲解Bean的生命周期的实现过程;

???~~~~最后希望与诸君共勉,共同进步!!!


???以上就是本期内容了, 感兴趣的话,就关注小编吧。

???期待你的关注~~~

相关文章:

【Spring Boot】Spring 魔法世界:Bean 作用域与生命周期的奇妙之旅

前言 ???本期讲解关于spring原理Bean的相关知识介绍~~~ ??感兴趣的小伙伴看一看小编主页&#xff1a;-CSDN博客 ?? 你的点赞就是小编不断更新的最大动力 ??那么废话不多说直接开整吧~~ 目录 ???1.Bean的作用域 ??1.1概念 ??1.2Bean的作用域 ??1.3代码演示…...

移远通信边缘计算模组成功运行DeepSeek模型,以领先的工程能力加速端侧AI落地

近日&#xff0c;国产大模型DeepSeek凭借其“开源开放、高效推理、端侧友好”的核心优势&#xff0c;迅速风靡全球。移远通信基于边缘计算模组SG885G&#xff0c;已成功实现DeepSeek模型的稳定运行&#xff0c;并完成了针对性微调。 目前&#xff0c;该模型正在多款智能终端上进…...

Cables Finance 构建集成LST与外汇RWA永续合约的综合性DEX

虽然 DeFi 领域整体发展迅速&#xff0c;但仍旧缺乏交易体验。现阶段市场已拓展至 RWAs 、永续期货和外汇领域&#xff0c;但跨资产交易的实际操作仍充满阻力。交易者面临流动性碎片化、抵押品被锁定在质押合约中缺乏流动性&#xff0c;以及整个系统仍围绕美元稳定币运转等问题…...

AI大模型(DeepSeek)科研应用、论文写作、数据分析与AI绘图学习

【介绍】 在人工智能浪潮中&#xff0c;2024年12月中国公司研发的 DeepSeek 横空出世以惊艳全球的姿态&#xff0c;成为 AI领域不可忽视的力量!DeepSeek 完全开源&#xff0c;可本地部署&#xff0c;无使用限制&#xff0c;保护用户隐私。其次&#xff0c;其性能强大&#xff…...

【算法工程】解决linux下Aspose.slides提示No usable version of libssl found以及强化推理模型的短板

1. 背景 构建ubuntu镜像&#xff0c;然后使用Aspose.slides解析PPTX文档&#xff0c;发现一直提示“No usable version of libssl found”。 2. 尝试 使用deepseek R1、kimi1.5、chatgpt o3&#xff0c;并且都带上联网能力&#xff0c;居然还是没有一个能够真正解决&#xf…...

什么是HTTP和HTTPS?它们之间有什么区别?

什么是HTTP和HTTPS&#xff1f;它们之间有什么区别&#xff1f; HTTP&#xff08;超文本传输协议&#xff09;简介 HTTP就像是你通过明信片给朋友发送信息。你在明信片上写下内容&#xff0c;然后寄出去。任何人都可以在途中看到明信片上的内容&#xff0c;因为它是公开的。 …...

【一文读懂】TCP与UDP协议

TCP协议 概述 TCP&#xff08;Transmission Control Protocol&#xff09;&#xff0c;即传输控制协议&#xff0c;是一种面向连接的、可靠的、基于字节流的传输层通信协议&#xff0c;常用于保证数据可靠、按顺序、无差错地传输。TCP 是互联网协议族&#xff08;TCP/IP&…...

数据结构 树的存储和遍历

一、树的定义 树的定义 树型结构是⼀类重要的⾮线性数据结构。 • 有⼀个特殊的结点&#xff0c;称为根结点&#xff0c;根结点没有前驱结点。 • 除根结点外&#xff0c;其余结点被分成M个互不相交的集合T1 、T2 、...、Tm T&#xff0c;其中每⼀个集合⼜是⼀棵树&#xff0c…...

Jenkins项目CICD流程

Jenkins项目流程:1.配置git环境 git config --...2.把前后端的目录初始化位本地工作目录 #git init3.提交到本地git #git add ./ git commit -m "" git tag v14.然后提交到远程git(通过,用户,群组,项目,管理项目)git remote add origin http://...git push -…...

EasyRTC轻量级SDK:智能硬件音视频通信资源的高效利用方案

在智能硬件这片广袤天地里&#xff0c;每一份资源的精打细算都关乎产品的生死存亡。随着物联网技术的疾速演进&#xff0c;实时音视频通信功能已成为众多设备的标配。然而&#xff0c;硬件资源的捉襟见肘&#xff0c;让开发者们常常陷入两难境地。EasyRTC&#xff0c;以它的极致…...

AI Agent未来走向何方?

AI Agent未来走向何方? 目录 AI Agent未来走向何方?AI推理支撑应用开发走向新赛道智能体成为AI应用的主流形式大模型应用正以AI Agent的主流形式赋能终端设备从大到小AI模型发展从通用转向垂直:小型语言模型(SLM)AI推理支撑应用开发走向新赛道 训练与推理,是AI 大模型两大核…...

Visual Studio Code的键盘快捷键

注意&#xff1a;如果您在Mac上访问此页面&#xff0c;您将看到Mac的键盘快捷键。如果您使用Windows或Linux访问&#xff0c;您将看到该平台的密钥。如果您需要其他平台的键盘快捷键&#xff0c;请将鼠标悬停在您感兴趣的键上。 键盘快捷键编辑器 VS Code通过键盘快捷键编辑器…...

【Jenkins流水线搭建】

Jenkins流水线搭建 01、SpringBoot项目 - Jenkins基于Jar持续集成搭建文档基于手动方式发布项目基于dockerfile基于jenkins + dockerfile + jenkinsfile +pieline基于jenkins + jar方式的发布01、环境说明01、准备项目02、准备服务器03、安装git04、安装jdk1.805、安装maven依赖…...

PHP 基础介绍

PHP 学习资料 PHP 学习资料 PHP 学习资料 PHP 是一种广泛使用的开源服务器端脚本语言&#xff0c;尤其适合 Web 开发&#xff0c;能轻松嵌入 HTML 中&#xff0c;生成动态网页内容。接下来&#xff0c;让我们一起了解 PHP 的基础内容。 一、PHP 的安装与配置 在开始编写 PH…...

DeepSeek如何重塑我的编程学习:计算机新生的AI实践

目录 &#x1f680;前言&#x1f31f;邂逅DeepSeek&#xff1a;从困惑到惊喜&#x1f4af;初学编程的困境&#x1f4af;DeepSeek的优势 &#x1f58a;️DeepSeek在编程学习中的运用&#x1f4af;注释&#x1f4af;算法逐步分析&#x1f4af;调试帮助&#x1f4af;跨语言迁移学习…...

spring boot和spring cloud的关系

Spring Boot和Spring Cloud之间的关系可以概括为构建和扩展的关系&#xff0c;其中Spring Boot提供了基础&#xff0c;而Spring Cloud在此基础上提供了分布式系统和微服务架构所需的扩展和工具。以下是两者关系的详细阐述&#xff1a; 一、基础与扩展 Spring Boot&#xff1a…...

ThreadLocal原理和存在问题

ThreadLocal 的工作原理 ThreadLocal 是 Java 提供的一个类&#xff0c;用于在多线程环境下存储线程局部变量。每个线程都可以独立地更改存储在其 ThreadLocal 变量中的值&#xff0c;而不会影响其他线程中的变量副本。ThreadLocal 的实现原理基于 Thread 类中的 ThreadLocal.…...

用Echarts的柱状图实现圆柱体效果

用Echarts的柱状图实现圆柱体效果 在数据可视化的世界里&#xff0c;Echarts凭借其强大的功能和丰富的特性&#xff0c;成为众多开发者的首选工具。本文将深入探讨如何利用Echarts的柱状图来实现独特的圆柱体效果&#xff0c;通过详细剖析代码&#xff0c;让大家了解其中的实现…...

Docker 常用命令基础详解(一)

一、Docker 初相识 在当今数字化时代&#xff0c;软件开发和部署的效率与灵活性成为了关键因素。Docker&#xff0c;作为一款开源的应用容器引擎&#xff0c;犹如一颗璀璨的明星&#xff0c;照亮了软件开发与部署的道路&#xff0c;为开发者们带来了前所未有的便利。它就像是一…...

Java并发中的CAS机制:原理、应用与挑战(通俗易懂版)

上一期文章内容&#xff1a;Java并发中的乐观锁与悲观锁&#xff0c; 本期文章我们来讲一下Java并发中的CAS机制 一、从银行账户案例理解CAS CAS 是一种乐观锁机制&#xff0c;用于在不使用锁的情况下实现多线程对共享资源的并发访问。 它包含三个操作数&#xff1a;内存位置&a…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...