Bean 作用域、生命周期和Spring执行流程

news2025/1/13 7:37:53

文章目录

  • Bean作用域问题案例分析
    • 公共 Bean
    • A 用户使用时修改
    • B 用户使用时
    • 原因分析
  • 作用域定义
    • Bean 的6种作用域
      • singleton
      • prototype
      • request
      • session
      • application
      • websocket
    • 设置作用域
  • Spring 执行流程
    • 1、启动容器
    • 2、Bean 初始化
    • 3、注册Bean对象到容器中
    • 4、装配Bean属性
  • Bean 生命周期
    • 1、实例化
    • 2、设置属性
    • 3、初始化
    • 4、使用Bean
    • 5、销毁Bean
  • 生命周期演示

Bean作用域问题案例分析

假设现在有⼀个公共的 Bean,提供给 A ⽤户和 B ⽤户使⽤,然⽽在使⽤的途中 A ⽤户却“悄悄”地修改了公共 Bean 的数据,导致 B ⽤户在使⽤时发⽣了预期之外的逻辑错误。

公共 Bean

@Component
public class DogBean {
    @Bean
    public Dog dog() {
        Dog dog = new Dog();
        dog.setName("旺财");
        dog.setId(1);
        dog.setAge(5);
        return dog;
    }
}

A 用户使用时修改

@Controller
public class ScopeController {

    @Autowired
    private Dog dog;

    public void doScope(){
        System.out.println("do scope controller");
        System.out.println("原始dog对象:" + dog.toString());

        Dog dog2 = dog;
        dog2.setAge(10);
        dog2.setId(2);
        dog2.setName("小黑");

        System.out.println("修改后的dog对象:" + dog.toString());
    }
}

在这里插入图片描述

B 用户使用时

@Controller
public class ScopeController2 {
    @Resource
    private Dog dog;

    public void doScope(){
        System.out.println("do scope controller2");

        System.out.println(dog.toString());
    }
}

在这里插入图片描述

原因分析

我们可以看到,B 用户在使用这个Bean对象时,得到的Dog是被A 用户修改过的,这无疑会给 B 用户带来很大的麻烦。操作以上问题的原因是因为 Bean 默认情况下是单例状态(singleton),也就是所有⼈的使⽤的都是同⼀个对象,之前我们学单例模式的时候都知道,使⽤单例可以很⼤程度上提⾼性能,所以在 Spring 中 Bean 的作⽤域默认也是 singleton 单例模式。

作用域定义

限定程序中变量的可⽤范围叫做作⽤域,或者说在源代码中定义变量的某个区域就叫做作⽤域。⽽ Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种⾏为模式,⽐如 singleton 单例作⽤域,就表示 Bean 在整个 Spring 中只有⼀份,它是全局共享的,那么当其他⼈修改了这个值之后,那么另⼀个⼈读取到的就是被修改的值。

Bean 的6种作用域

Spring 容器在初始化⼀个 Bean 的实例时,同时会指定该实例的作⽤域。Spring有 6 种作⽤域,最后
四种是基于 Spring MVC ⽣效的:

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

后4种状态是Spring MVC 中的值,在普通的 Spring 项目中只有前两种。

singleton

  • 官⽅说明:(Default) Scopes a single bean definition to a single object instance for each Spring IoC container.
  • 描述:该作⽤域下的Bean在IoC容器中只存在⼀个实例:获取Bean(即通过applicationContext.getBean等⽅法获取)及装配Bean(即通过@Autowired注⼊)都是同⼀个对象。
  • 场景:通常⽆状态的Bean使⽤该作⽤域。⽆状态表示Bean对象的属性状态不需要更新
  • 备注:单例模式默认的作用域,只有一个全局对象

prototype

  • 官⽅说明:Scopes a single bean definition to any number of object instances.
  • 描述:每次对该作⽤域下的Bean的请求都会创建新的实例:获取Bean(即通过applicationContext.getBean等⽅法获取)及装配Bean(即通过@Autowired注⼊)都是新的对象实例。
  • 场景:通常有状态的Bean使⽤该作⽤域
  • 备注:原型模式【多例默认】,每次访问都会创建一个新对象

request

  • 官⽅说明:Scopes a single bean definition to the lifecycle of a single HTTP request. That is,each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
  • 描述:每次http请求会创建新的Bean实例,类似于prototype
  • 场景:⼀次http的请求和响应的共享Bean
  • 备注:限定SpringMVC中使⽤

session

  • 官⽅说明:Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
  • 描述:在⼀个http session中,定义⼀个Bean实例
  • 场景:⽤户回话的共享Bean, ⽐如:记录⼀个⽤户的登陆信息
  • 备注:限定SpringMVC中使⽤

application

  • 官⽅说明:Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
  • 描述:在⼀个http servlet Context中,定义⼀个Bean实例
  • 场景:Web应⽤的上下⽂信息,⽐如:记录⼀个应⽤的共享信息
  • 备注:限定SpringMVC中使⽤

websocket

  • 官⽅说明:Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.
  • 描述:在⼀个HTTP WebSocket的⽣命周期中,定义⼀个Bean实例
  • 场景:WebSocket的每次会话中,保存了⼀个Map结构的头信息,将⽤来包裹客户端消息头。第⼀次初始化后,直到WebSocket结束都是同⼀个Bean。
  • 备注:限定Spring WebSocket中使⽤

设置作用域

使⽤ @Scope 标签就可以⽤来声明 Bean 的作⽤域,@Scope 标签既可以修饰⽅法也可以修饰类,@Scope 有两种设置⽅式:

  1. 直接设置值:@Scope(“prototype”)
  2. 使⽤枚举设置:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Component
public class DogBean {
    @Scope("prototype")
    @Bean
    public Dog dog() {
        Dog dog = new Dog();
        dog.setName("旺财");
        dog.setId(1);
        dog.setAge(5);
        return dog;
    }
}

这样设置完成后,A 用户的修改对 B 用户的使用就不会造成影响了。

Spring 执行流程

1、启动容器

在这里插入图片描述

2、Bean 初始化

配置文件中的bean、配置了加载组件路径下的类进行扫描【看有没有类注解】
在这里插入图片描述

3、注册Bean对象到容器中

通过五大注解来把对象注入到容器中,并且只有在包扫描路径上的类,且使用Spring的注解才可以被注册到容器中。
在这里插入图片描述

具体参考博客:使用spring注解储存对象

4、装配Bean属性

如果Bean对象 需要使用其他Bean对象作为属性,可以使用注解@Autowired、@Resource
在这里插入图片描述
具体参考博客:spring依赖注入

Bean 生命周期

在这里插入图片描述

1、实例化

这是生命周期的第一步。在这个阶段,Spring会创建一个Bean的实例。这就像在工厂里制造一个产品一样,但在这里,Spring负责创建和管理Bean对象。

2、设置属性

一旦Bean实例化了,Spring会通过依赖注入的方式设置Bean的属性。这就像给产品添加特性和功能一样。你可以在配置文件中指定属性值,然后Spring会把这些值设置给Bean。

3、初始化

在这个阶段,Bean被初始化。你可以定义初始化方法,Spring会在设置属性后调用这些方法。这允许你在Bean准备好之前做一些额外的设置或者操作。

  1. 执行各种通知: 实现了各种 Aware 通知的方法,如 BeanNameAware、BeanFactoryAware、ApplicationContextAware 的接口方法;
  2. BeanPostProcessor的前置处理(postProcessBeforeInitialization): 如果在应用中定义了BeanPostProcessor接口的实现类,Spring会在Bean初始化之前调用这些实现类的postProcessBeforeInitialization方法。这提供了一个机会,你可以在Bean被初始化之前进行一些定制化的操作。
  3. 初始化方法(InitializingBean和init-method): 如果Bean实现了InitializingBean接口,Spring会在属性设置后调用它的afterPropertiesSet方法。执⾏ @PostConstruct 初始化⽅法,依赖注⼊操作之后被执⾏。此外,你还可以通过配置指定一个自定义的初始化方法(通常使用init-method属性)。在这个方法中,你可以执行任何你需要在Bean初始化时完成的逻辑。
  4. BeanPostProcessor的后置处理(postProcessAfterInitialization): 类似于前置处理,如果有BeanPostProcessor接口的实现类,Spring会在Bean初始化之后调用这些实现类的postProcessAfterInitialization方法。这个阶段可以用来进行一些额外的操作,例如修改Bean的属性或状态。

4、使用Bean

一旦Bean被初始化,它就准备好被使用了。你可以在应用程序的其他部分中引用并使用这个Bean,执行你所需的操作。这就像使用你制造的产品一样。

5、销毁Bean

当应用程序关闭或者不再需要Bean时,Spring会执行销毁操作。你可以定义销毁方法,在Bean不再需要时执行一些清理工作,比如关闭数据库连接或者释放资源。

生命周期演示

package com.fyd.controller;

import org.springframework.beans.factory.BeanNameAware;

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

public class BeanLifeComponent implements BeanNameAware {
    @Override
    public void setBeanName(String name) {
        System.out.println("执行了 Bean Name 通知" + name);
    }


    public void init(){
        System.out.println("执行了 init 方法");
    }

    @PostConstruct
    public void myPostConstruct(){
        System.out.println("执行了 myPostConstruct 方法");
    }

    /**
     * 销毁前执行方法
     */
    @PreDestroy
    public void myPreDestroy(){
        System.out.println("执行了 myPreDestroy 方法");
    }

    public void use(){
        System.out.println("执行了 use 方法");
    }
}

xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd ">


    <context:component-scan base-package="com.fyd"/>

    <bean id="beanlife" class="com.fyd.controller.BeanLifeComponent"
    init-method="init"></bean>
    
</beans>

调用代码

import com.fyd.controller.BeanLifeComponent;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanLifeTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");

        BeanLifeComponent beanLifeComponent = context.getBean("beanlife",BeanLifeComponent.class);
        beanLifeComponent.use();
        // 关闭容器
        context.destroy();

    }
}

执行结果:
在这里插入图片描述

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

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

相关文章

【C++11新特性】右值引用和移动语义

文章目录 1. 左值与右值1.1 左值与右值对比1.2 左值引用与右值引用 2. 右值引用的使用场景2.1 左值引用的短板2.2 右值引用和移动语义2.3 右值引用对左值的引用 3. 完美转发3.1 万能引用3.2 完美转发保持值的属性 1. 左值与右值 1.1 左值与右值对比 左值的概念 左值是一个表示…

13 MySQL

文章目录 MySQL基本使用安装RDBMS使用Navicat新建数据库新建查询--即代码运行的地方运行代码表的操作 命令行连接数据完整性数据类型约束 SQL的基础语法特性&#xff1a;SQL语句的分类DDL库管理 DDL表管理&#xff1a;DML(增删改)新增删除更新 DQL(查)DQL基础查询as 取别名消除…

Java查看https证书过期时间(JKS,CERT)

在这里需要使用X.509 证书的抽象类 X509Certificate 。此类提供了一种访问 X.509 证书所有属性的标准方式。 这些证书被广泛使用以支持 Internet 安全系统中的身份验证和其他功能。常见的应用包括增强保密邮件 (PEM)、传输层安全 (SSL)、用于受信任软件发布的代码签名和安全电…

MongoDB 数据库

目录 一、概述 二、相关概念 三、特性 四、应用的场景 五、安装及配置文件操作 一、首先配置好环境 二、安装 三、查看端口号 四、查看配置文件 五、查询已安装的软件包 六、树状图解析 六、默认数据库&#xff08;默认有admin、local、config三个&#xff09; 一…

Java后端开发面试题篇——Redis

Redis的数据持久化策略有哪些 RDB的执行原理&#xff1f; bgsave开始时会fork主进程得到子进程&#xff0c;子进程共享主进程的内存数据。完成fork后读取内存数据并写入 RDB 文件。 fork采用的是copy-on-write技术&#xff1a; 当主进程执行读操作时&#xff0c;访问共享内存…

SQL-每日一题【1587. 银行账户概要 II】

题目 表: Users 表: Transactions 编写解决方案, 报告余额高于 10000 的所有用户的名字和余额. 账户的余额等于包含该账户的所有交易的总和。 返回结果表单 无顺序要求 。 查询结果格式如下例所示。 示例 1&#xff1a; 解题思路 1.题目要求我们查询出额高于 10000 的所有…

Yalmip入门教程(5)-约束条件操作的相关函数

博客中所有内容均来源于自己学习过程中积累的经验以及对yalmip官方文档的翻译&#xff1a;https://yalmip.github.io/tutorials/ 这篇博客将详细介绍yalmip工具箱中约束条件操作相关函数的用法。 1.约束条件操作的相关函数 1.1 boundingbox函数 boundingbox函数用于求出一组约…

Java基本变量

概念&#xff1a; 本质上来说变量是内存中的一小块区域&#xff0c;通过变量名来访问这块区域。因此&#xff0c;使用每一个变量前必须要先申请&#xff08;声明&#xff09;然后必须对其进行赋值&#xff0c;才能使用。 基本数据类型&#xff08;在栈stack中&#xff09; 整…

【从0开始学架构笔记】01 基础架构

文章目录 一、架构的定义1. 系统与子系统2. 模块与组件3. 框架与架构4. 重新定义架构 二、架构设计的目的三、复杂度来源&#xff1a;高性能1. 单机复杂度2. 集群复杂度2.1 任务分配2.2 任务分解&#xff08;微服务&#xff09; 四、复杂度来源&#xff1a;高可用1. 计算高可用…

Python爬虫解析工具之xpath使用详解

文章目录 一、数据解析方式二、xpath介绍三、环境安装1. 插件安装2. 依赖库安装 四、xpath语法五、xpath语法在Python代码中的使用 一、数据解析方式 爬虫抓取到整个页面数据之后&#xff0c;我们需要从中提取出有价值的数据&#xff0c;无用的过滤掉。这个过程称为数据解析&a…

网络技术Vlan技术STP(第一课)

一 Vlan技术的学习 对命令的增删改查 #### 1&#xff09;创建vlan[SW1]vlan 2 [2-4094] 创建vlan[SW1]vlan batch 10 20 30 创建多个不连续的vlan[SW1]display vlan 查看vlan信息[SW1]vlan batch 50 to 60创建多个连续的vlan[SW1]vlan2[SW1-vlan2]description caiwu添加描述信…

基于决策树(Decision Tree)的乳腺癌诊断

决策树(DecisionTree)学习是以实例为基础的归纳学习算法。算法从--组无序、无规则的事例中推理出决策树表示形式的分类规则,决策树也能表示为多个If-Then规则。一般在决策树中采用“自顶向下、分而治之”的递归方式,将搜索空间分为若千个互不相交的子集,在决策树的内部节点(非叶…

AutoSAR配置与实践(基础篇)3.3 BSW的通信功能

传送门 -> AUTOSAR配置与实践总目录 AutoSAR配置与实践&#xff08;基础篇&#xff09;3.3 BSW的通信功能 一、收发过程概览1.1 发送过程概览1.2 接收过程概览 二、BSW的通信功能模块组成三、收发过程解析3.1 发送过程3.2 发送后的结果确认3.3 接收过程 一、收发过程概览 1…

图像编程补充:计算机图形学和数字图像处理概念

一、计算机图形学 国际标准化组织&#xff08;ISO&#xff09;的定义&#xff1a;计算机图形学是研究通过计算机将数据转换为图形&#xff0c;并在专门显示设备上显示的原理、方法和技术的学科。 1.1什么是计算机图形学 图形的构成要素&#xff1a; 图形的广义概念&#xff1…

TCP拥塞控制简单理解

1.TCP的控制机制 序号 TCP通过序号可以实现一下几个功能&#xff1a; 1.确认应答处理。发送端收到接收端的确认应答&#xff0c;可以得知某些数据包被接收端接收了 2.顺序控制。接收端可以利用序号对接收到的报文进行排序 3.重发控制。如果发送端没有收到确认应答&#xff0c…

【MT32F006】MT32F006之定时器延时

本文最后修改时间&#xff1a;2023年03月30日 一、本节简介 本文介绍如何使用MT32F006的定时器做us、ms级的延时。 二、实验平台 库版本&#xff1a;V1.0.0 编译软件&#xff1a;MDK5.37 硬件平台&#xff1a;MT32F006开发板&#xff08;主芯片MT32F006&#xff09; 仿真器…

【C语言】每日一题(找到所有数组中消失的数字)

找到所有数组中消失的数字&#xff0c;链接奉上。 这里简单说一下&#xff0c;因为还没有接触到动态内存&#xff0c;数据结构&#xff0c;所以知识有限&#xff0c;也是尽力而为&#xff0c;结合题库的评论区找到了适合我的解法&#xff0c;以后有机会&#xff0c;会补上各种…

麻辣烫数据可视化,麻辣烫市场将持续蓬勃发展

麻辣烫&#xff0c;这道源自中国的美食&#xff0c;早已成为人们生活中不可或缺的一部分。它独特的香辣口味&#xff0c;让人忍不住每每流连忘返。与人们的关系&#xff0c;简直如同挚友一般。每当寒冷的冬日或疲惫的时刻&#xff0c;麻辣烫总是悄然走进人们的心房&#xff0c;…

Winload.efi丢失或损坏怎么办?

Winload.efi是一个EFI&#xff08;或可扩展固件接口&#xff09;文件。可执行的EFI文件适用于基于计算机系统的UEFI&#xff0c;并将文件加载到计算机引导加载程序的执行任务。它们包含有关操作系统引导过程应如何进行的重要数据。因此&#xff0c;Winload.efi文件对于成功启动…

大数据Flink学习圣经:一本书实现大数据Flink自由

学习目标&#xff1a;三栖合一架构师 本文是《大数据Flink学习圣经》 V1版本&#xff0c;是 《尼恩 大数据 面试宝典》姊妹篇。 这里特别说明一下&#xff1a;《尼恩 大数据 面试宝典》5个专题 PDF 自首次发布以来&#xff0c; 已经汇集了 好几百题&#xff0c;大量的大厂面试…