Spring Bean 的生命周期与作用域解析及实战

引言

在Spring框架中,Bean是构成应用的核心组件,它们负责执行应用中的业务逻辑。理解Spring Bean的生命周期和作用域对于开发高效、稳定的Spring应用至关重要。本文将详细解析Spring Bean的生命周期和作用域,并通过实战案例加深理解。

一、Spring Bean的生命周期

Spring Bean 的生命周期指的是Bean从创建到销毁的整个过程。这个过程包括Bean的实例化、属性赋值、初始化以及销毁等阶段。了解Bean的生命周期可以帮助我们更好地管理Bean的状态和行为。

  1. 实例化:Spring IoC容器根据配置创建Bean的实例。
  2. 属性赋值:通过依赖注入的方式,为Bean的属性赋值。
  3. 初始化:在Bean的所有属性设置完成之后,如果Bean实现了InitializingBean接口,会调用其 afterPropertiesSet() 方法进行初始化;或者如果在配置文件中指定了init-method,则会调用指定的初始化方法。
  4. 使用:Bean初始化完成后,就可以被应用的其他部分使用。
  5. 销毁:当容器关闭时,如果Bean实现了 DisposableBean 接口,会调用其destroy() 方法进行销毁;或者在配置文件中指定了 destroy-method,则会调用指定的销毁方法
    在这里插入图片描述

二、Spring Bean的作用域

Spring Bean的作用域决定了Bean的实例在Spring IoC容器中的生命周期和可见性。

Spring支持以下几种作用域:

  1. Singleton(单例)

这是Spring默认的作用域。当一个Bean定义为Singleton时,IoC容器中只会存在一个该Bean的共享实例。对于整个应用上下文,每次请求该Bean时,容器都会返回相同的实例。Singleton作用域的Bean在容器启动时或首次请求时被创建(如果配置了懒加载,则在首次实际请求时创建)。

  1. Prototype(原型)

Prototype作用域的Bean在每次请求时都会创建一个新的实例。这意味着每次通过容器的getBean()方法获取该Bean时,都将获得一个新的对象。这对于有状态的Bean(即保存实例变量状态的Bean)非常有用,因为每个用户或每次请求都需要独立的状态。
Request(请求):

该作用域仅在Web应用程序的WebApplicationContext中可用。每次HTTP请求都会创建一个新的Bean实例,且该实例仅在当前请求的生命周期内有效。

  1. Session(会话)

同样仅限于Web环境,每个HTTP Session都会创建一个Bean的新实例,并且该Bean实例在Session生命周期内有效。不同的用户或不同的浏览器会话将拥有不同的Bean实例。

  1. Global Session(全局会话)

这个作用域也是Web环境特有的,主要应用于Portlet环境中。它类似于标准的Session作用域,但针对portlet的全局会话,即跨越多个Portlet窗口。

除此之外,还有如application(全局作用域,对应于ServletContext的生命周期)和 websocket(HTTP WebSocket作用域,与单个WebSocket连接的生命周期相关联)等其他不那么常见的作用域,但它们的使用不如上述几种普遍。

我们可以根据Bean的具体用途选择合适的作用域,以优化资源管理和应用性能。在Spring中,可以通过XML配置文件中的标签的scope属性或者Java配置中的@Scope注解来定义Bean的作用域

三、实战案例

下面通过一个简单的实战案例来演示Spring Bean的生命周期和作用域。

首先,定义一个简单的UserService类,并实现InitializingBean和DisposableBean接口:

import org.springframework.beans.factory.DisposableBean;  
import org.springframework.beans.factory.InitializingBean;  
  
public class UserService implements InitializingBean, DisposableBean {  
    private String message;  
  
    public void setMessage(String message) {  
        this.message = message;  
    }  
  
    public void doSomething() {  
        System.out.println("UserService is doing something: " + message);  
    }  
  
    @Override  
    public void afterPropertiesSet() throws Exception {  
        System.out.println("UserService is initializing...");  
    }  
  
    @Override  
    public void destroy() throws Exception {  
        System.out.println("UserService is destroying...");  
    }  
}

然后,使用Java配置类来定义Bean:

import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.context.annotation.Scope;  
  
@Configuration  
public class AppConfig {  
  
    @Bean  
    @Scope("prototype") // 设置作用域为prototype  
    public UserService userService() {  
        return new UserService();  
    }  
}

在主程序中,我们创建Spring应用上下文,获取UserService的Bean实例,并调用其方法:

import org.springframework.context.ApplicationContext;  
import org.springframework.context.annotation.AnnotationConfigApplicationContext;  
  
public class MainApp {  
    public static void main(String[] args) {  
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);  
  
        // 获取两个prototype作用域的Bean实例  
        UserService userService1 = context.getBean(UserService.class);  
        UserService userService2 = context.getBean(UserService.class);  
  
        // 输出Bean的hashCode以验证是否为不同实例  
        System.out.println("userService1 hashCode: " + userService1.hashCode());  
        System.out.println("userService2 hashCode: " + userService2.hashCode());  
  
        // 调用Bean的方法  
        userService1.doSomething();  
        userService2.doSomething();  
  
        // 关闭应用上下文,触发Bean的销毁逻辑  
        ((AnnotationConfigApplicationContext) context).close();  
    }  
}

运行上述程序,你将看到控制台输出以下信息:

userService1 hashCode: [someHashCode1]  
userService2 hashCode: [someHashCode2]  
UserService is initializing...  
UserService is doing something: null  
UserService is initializing...  
UserService is doing something: null  
UserService is destroying...  
UserService is destroying...

从输出中可以看到,userService1和userService2的hashCode不同,说明它们是两个不同的实例,这验证了prototype作用域的行为。同时,每次获取Bean时都会调用初始化方法,并且在应用上下文关闭时调用了销毁方法。

四、总结

通过本文的讲解和实战应用,我们深入了解了Spring Bean的生命周期和作用域。Bean的生命周期包括实例化、属性赋值、初始化、使用和销毁等阶段,而作用域则决定了Bean实例在IoC容器中的存在范围。合理利用这些概念,可以帮助我们更好地管理和优化Spring应用中的Bean,提高应用的性能和稳定性。

在日常开发中,我们还需要注意以下几点:

  • 避免在Bean的初始化或销毁方法中执行耗时的操作,以免影响应用的启动和关闭速度。

  • 对于单例作用域的Bean,要注意线程安全问题,避免在多线程环境下出现数据不一致的情况。

  • 根据实际需求选择合适的作用域,避免不必要的Bean创建和销毁,提高资源利用率。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

人工智能好多人都在用,那么用户画像要怎么看?

用户画像是通过对用户行为、偏好、兴趣等数据进行分析和整理,从而形成的关于特定用户群体的描述和模型。在人工智能应用中,用户画像可以起到指导个性化推荐、精准营销、产品设计等方面的作用。以下是用户画像在人工智能应用中的几个重要方面:…

网站被SmartScreen标记为不安全怎么办?

在互联网时代,网站的安全性和可信度是用户选择是否继续访问的重要因素之一,然而,网站运营者偶尔会发现使用Edge浏览器访问网站时,会出现Microsoft Defender SmartScreen(以下简称SmartScreen)提示网站不安全…

上位机图像处理和嵌入式模块部署(树莓派4b之mcu固件升级)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 在一个系统当中,可能不止需要树莓派4b一个设备,有的时候还需要搭载一个mcu,做一些运动控制的事情。比如说&…

SRAM控制原理与读写实例

本文对SRAM进行介绍,并对其内部的存储器矩阵、地址译码器、列I/O及I/O数据电路、控制电路、SRAM的读写流程进行简要介绍,并给出SRAM IS62LV256-45U读写实例。 文章目录 存储容量的计算SRAM控制原理SRAM信号线存储器矩阵地址译码器、列I/O及I/O数据电路控…

陆游只爱前妻唐婉,深情大渣男太虐了

陆游和唐婉的感情太好了,经常写诗逗乐。陆游科举考不上,沉迷儿女情长,被母亲拆散。 秦侩当政,就是害死岳飞的那个秦桧。陆游第二次考进士,被秦侩批复“喜论恢复”,没考上。陆游的母亲生气,找个…

计算机视觉——两视图几何求解投影矩阵

上文我提到了通过图像匹配得到基本矩阵,接下来我们要接着求解投影矩阵。 计算投影矩阵思路 假设两个投影矩阵为规范化相机,因此采用基本矩阵进行恢复。在规范化相机下, P [ I ∣ 0 ] P[I|0] P[I∣0], P ′ [ M ∣ m ] P[M|m] P′[M∣m]。…

【Webgl_glslThreejs】搬运分享shader_飘落心形

来源网站 https://www.shadertoy.com/view/4sccWr效果预览 代码演示 将shadertory上的代码转成了threejs可以直接用的代码,引入文件的material,并在创建mesh或已有物体上使用material即可,使用时请注意uv对齐。 import { DoubleSide, Shad…

视频中为什么需要这么多的颜色空间?

在视频处理中,经常会用到不同色彩空间:非线性RGB,线性 RGB,YUV,XYZ……为什么需要这么多的色彩空间呢? 1、视频采集时的线性RGB颜色空间 由数码相机中的 CMOS 传感器产生并写入原始文件(Raw Fil…

深度学习检测算法YOLOv5的实战应用

在当前的检测项目中,需要一个高效且准确的算法来处理大量的图像数据。经过一番研究和比较,初步选择了YOLOv5作为算法工具。YOLOv5是一个基于深度学习的检测算法,以其快速和准确而闻名。它不仅能够快速处理图像数据,还能提供较高的…

区块链技术与应用学习笔记(12-13节)——北大肖臻课程

目录 12.BTC-匿名性 一、什么是匿名? 1,有可能破坏比特币匿名性的两个方面 2,如何提高匿名性 一个比特币用户能采用什么样的方法尽量提高个人的匿名性? 分解: 1、网络层怎么提高匿名性? 2、应用层怎么提高匿名性? 零知…

揭露 FileSystem 引起的线上 JVM 内存溢出问题

作者:来自 vivo 互联网大数据团队-Ye Jidong 本文主要介绍了由FileSystem类引起的一次线上内存泄漏导致内存溢出的问题分析解决全过程。 内存泄漏定义(memory leak):一个不再被程序使用的对象或变量还在内存中占有存储空间&#x…

无人机生态环境监测、图像处理与 GIS 数据分析

原文链接:无人机生态环境监测、图像处理与 GIS 数据分析https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247602414&idx6&sn950b55bc2cc4812c838c66af2118d74e&chksmfa821109cdf5981f2af51bd27e459a1c46dd783cdceba5aa3693461260bbf7b0101ac8…

Vim学习笔记01~04

第01章: 遁入空门,模式当道 1.什么是vim Vim是一个高效的文本编辑工具,并且可以在编程开发过程中发挥越来越重要的作用。 事实上,有不少编程高手使用他们来进行代码的开发,并且对此赞不绝口。 2.本系列目的 但是让…

Java作业7-Java异常处理

异常处理这块有些不太理解,看看Bz网课-异常 编程1-计算器输入异常 题目 计算器输入异常 在实验三中实现的命令行计算器已有功能基础上,添加异常处理机制,当用户输入的操作数为非整数时,利用异常处理机制显示错误提示信息。如&a…

网易云热评加密函数逆向(Jsrpc)

今天给大家来个jsrpc实战教程,让大家继续加深对jsrpc的理解和认识。 1、因为网易云音乐热评的加密并不在cookie上,而是参数加密,所以这里就不需要进行hook住cookie了。 2、之前就知道网易云音乐热评的加密存在之地是在下图的位置,是那个函数window.asrsea(JSON.stringify(…

项目实战 | 责任链模式 (下)

案例二:工作流,费用报销审核流程 同事小贾最近刚出差回来,她迫不及待的就提交了费用报销的流程。根据金额不同,分为以下几种审核流程。报销金额低于1000元,三级部门管理者审批即可,1000到5000元除了三级部…

免费分享一套SpringBoot+Vue家政服务管理平台管理系统,帅呆了~~

大家好,我是java1234_小锋老师,看到一个不错的SpringBootVue家政服务管理平台管理系统,分享下哈。 项目视频演示 【免费】SpringBootVue家政服务管理平台系统 Java毕业设计_哔哩哔哩_bilibili【免费】SpringBootVue家政服务管理平台系统 Ja…

coverage,一个有趣的 Python 库!

更多Python学习内容:ipengtao.com 大家好,今天为大家分享一个有趣的 Python 库 - coveragepy。 Github地址:https://github.com/nedbat/coveragepy 在软件开发中,测试是确保代码质量和稳定性的关键步骤之一。而代码覆盖率则是衡量…

2024新版计算机网络视频教程65集完整版(视频+配套资料)

今日学计算机网络,众生皆叹难理解。 却见老师神乎其技,网络通畅如云烟。 协议层次纷繁复杂,ARP、IP、TCP、UDP。 路由器交换机相连,数据包穿梭无限。 网络安全重于泰山,防火墙、加密都来添。 恶意攻击时刻存在&#xf…

深圳证券交易所Binary行情数据接口规范

对接深圳证券交易所Binary行情数据接口其实并不难,你需要具备以下知识。 1、需要了解Binary报文设计结构,消息头消息体消息尾。 消息体: 如果是纯map结构的比较简单,字段平铺开来即可。如{"id":"1","…