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

news2024/11/18 12:29:21

引言

在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创建和销毁,提高资源利用率。

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

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

相关文章

使用FunASR处理语音识别

FunASR是阿里的一个语音识别工具,比SpeechRecognition功能多安装也很简单; 官方介绍:FunASR是一个基础语音识别工具包,提供多种功能,包括语音识别(ASR)、语音端点检测(VAD&#xff…

微软ML Copilot框架释放机器学习能力

摘要:大模型席卷而来,通过大量算法模型训练推理,能根据人类输入指令产生图文,其背后是大量深度神经网络模型在做运算,这一过程称之为机器学习,本文从微软语言大模型出发,详解利用大型语言模型&a…

Java设计模式:使用责任链模式和状态模式优化‘审批流程‘

Java设计模式:使用责任链模式和状态模式优化审批流程 摘要引言 需求流程图正文内容📐 基本概念介绍 功能实现示例1:设计模式:责任链模式方法:好处: 示例2:设计模式:责任链模式方法和操作流程:好…

【stm32】swjtu西南交大嵌入式实验三 外部中断实验:按键中断

实验内容: 1、编写程序,设置主程序:跑马灯以 0.2s 的速度旋转;将 KB1 设置为外部中断,下 降沿触发,按下 KB1 则全彩灯的 R 灯闪烁 5 次。编译、下载程序到开发板,观察实 验现象;按下…

torch.cuda.is_avaliable()在命令行里是true,pycharm是false【省流:换Pycharm】

我的问题: 1、torch.cuda.is_avaliable()在命令行里是true,但是pycharm是false 2、pycharm选择pytorch所在的解释器,加载失败。 3、pytorch所在的解释器加载成功,但是里边的torch包莫名消失。 解决方法: 在调试了很…

Sping源码(七)—context: component-scan标签如何扫描、加载Bean

序言 简单回顾一下。上一篇文章介绍了从xml文件context component-scan标签的加载流程到ConfigurationClassPostProcessor的创建流程。 本篇会深入了解context component-scan标签底层做了些什么。 component-scan 早期使用Spring进行开发时,很多时候都是注解 标…

免费好用各科目的刷题软件

一 、前言 刷题,即通过大量做题来提高解题能力和考试成绩的行为,主要有以下几个好处: 1. 熟悉题型和考试格式 通过刷题,可以对考试中可能出现的题型和格式有更深入的了解,有助于在实际考试中快速识别题目类型和解题…

Java使用IText根据pdf模板创建pdf文件

1.导包 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.10</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-as…

mdk输出本语句在源程序中行数以及函数名称

代码如下&#xff1a; /* USER CODE BEGIN WHILE */while (1){printf("anlog uart1 test 2024-4-16\r\n");printf("[%s] %d\r\n",__func__,__LINE__);printf("[%s] %d",__func__,__LINE__);HAL_Delay(200);/* USER CODE END WHILE *//* USER COD…

MyBatis源码之MyBatis中SQL语句执行过程

MyBatis源码之MyBatis中SQL语句执行过程 SQL执行入口 我们在使用MyBatis编程时有两种方式&#xff1a; 方式一代码如下&#xff1a; SqlSession sqlSession sqlSessionFactory.openSession(); List<Student> studentList sqlSession.selectList("com.sjdwz.da…

AWS SES发送邮件如何正确配置?操作指南?

AWS SES发送邮件有哪些限制&#xff1f;AWS SES发信的注意事项&#xff1f; AWS SES作为亚马逊云服务提供的一项高效、可靠的电子邮件发送服务&#xff0c;受到了众多企业的青睐。然而&#xff0c;如何正确配置AWS SES发送邮件。AokSend将详细解析AWS SES发送邮件的配置过程&a…

GO语言写Prometheus自定义node-exporter的Docker容器测试

1. 安装docker-compose 执行以下命令&#xff0c;安装docker-compose到CentOS7.9环境中&#xff1a; # 下载二进制文件 sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.7/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/d…

耐酸碱腐蚀PFA冷凝回流装置进口透明聚四氟材质PFA梨形漏斗特氟龙圆底烧瓶

PFA分液漏斗&#xff1a;也叫特氟龙分液漏斗、特氟龙梨型分液漏斗。 规格参考&#xff1a;125ml、250ml、500ml、1000ml 其主要特性有&#xff1a; 1.内壁对溶剂无粘贴性和吸附&#xff0c;可完全排空&#xff0c;分界面清晰可见&#xff1b; 2.密封性好&#xff0c;可防止…

Laravel 6 - 第十七章 配置数据库

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

【C++题解】1043. 行李托运价格

问题&#xff1a;1043. 行李托运价格 类型&#xff1a;分支 题目描述&#xff1a; 某车站行李托运收费标准是&#xff1a; 10 公斤或 10 公斤以下&#xff0c;收费 2.5 元&#xff0c;超过 10 公斤的行李&#xff0c;按每超过 1 公斤增加 1.5 元进行收费。 试编一程序&#x…

python:pyqt5案例(简易浏览器)

1、上接pyqt5基础https://blog.csdn.net/weixin_73011353/article/details/138051734https://blog.csdn.net/weixin_73011353/article/details/138051734 2、基本模块 # 定义一个名为BrowserWindow的类&#xff0c;继承自QMainWindow class BrowserWindow(QMainWindow):def _…

[实验]Keil 4下仿真三星2440A芯片的汇编及CPIO控制实验

一、安装Keil uVision4 (详细安装过程忽略) 点击finish完成安装 二、新建项目&#xff0c;导入项目文件 选择对应的芯片&#xff0c;此处我们选择三星的S3C2440A&#xff0c;点击OK 在Source Group 1处右键&#xff0c;点击Add Files to "Sourcce Group 1’…将下图…

一文读懂VR数字展览会,从沉浸式体验到市场竞争力的全方位提升

在数字化转型的浪潮中&#xff0c;VR技术正逐渐成为商业展览的新趋势。VR数字展览会通过创新的展示功能和互动体验&#xff0c;为参展商和观众带来前所未有的便利和效果。 一、VR展示功能的沉浸式体验 1、全方位沉浸式体验&#xff1a; VR技术能够创造一个全方位的三维展览环…

MemFire案例-政务应急物联网实时监测预警项目

客户背景 党的十八大以来&#xff0c;中央多次就应急管理工作做出重要指示&#xff1a;要求坚持以防为主、防抗救相结合&#xff0c;全面提升综合防灾能力&#xff1b;坚持生命至上、安全第一&#xff0c;完善安全生产责任制&#xff0c;坚决遏制重特大安全事故。 面对新形势…

VSCODE自定义代码片段简述与基础使用

目录 一、 简述二 、 基础使用说明2.1 新建一个代码块工作区间2.2 语法 三、 示例四、 参考链接 一、 简述 VSCode的自定义代码片段功能允许开发者根据自己的需求定义和使用自己的代码片段&#xff0c;从而提高编码效率。 优点: 提高效率&#xff1a; 自定义代码片段能够减少…