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

文章目录

  • 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();

    }
}

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

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

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

相关文章

redis 存储结构原理 1

关于 redis 相信大家都不陌生了&#xff0c;之前有从 0 -1 分享过 redis 的基本使用方式&#xff0c;用起来倒是都没有啥问题了&#xff0c;不过还是那句话&#xff0c;会应用之后&#xff0c;我们必须要究其原理&#xff0c;知其然知其所以然 今天我们来分享一下关于 redis 的…

“维度削减+逻辑回归”:如何使用PCA大幅提升乳腺癌的预测成功率?

一、引言 乳腺癌是女性中最常见的恶性肿瘤之一&#xff0c;也影响着全球范围内许多人们的健康。据世界卫生组织&#xff08;WHO&#xff09;的数据&#xff0c;乳腺癌是全球癌症发病率和死亡率最高的肿瘤之一&#xff0c;其对个体和社会的危害不可忽视。因此&#xff0c;早期乳…

Coremail参与编制|《信创安全发展蓝皮书——系统安全分册(2023年)》

信创安全发展蓝皮书 近日&#xff0c;Coremail参与编制的《信创安全发展蓝皮书—系统安全分册&#xff08;2023年&#xff09;》重磅发布。 此次信创安全发展蓝皮书由工业和信息化部电子第五研究所联合大数据协同安全技术国家工程研究中心重磅共同发布。 本次蓝皮书涵盖信创系…

使用el-tree实现自定义树结构样式

实现效果: 直接上代码: <template><div><div class"tops"><el-tree :default-expanded-keys"[1]" ref"myTree" :data"data" :props"defaultProps" node-click"handleNodeClick" highlight…

广州华锐互动:奶牛难产原因及救治VR仿真实训系统

奶牛难产是一种常见的疾病&#xff0c;对奶牛的健康和生产造成很大的影响。为了解决这一问题&#xff0c;许多奶牛养殖场开始采用VR仿真技术来培训奶牛兽医&#xff0c;帮助学生更好地理解奶牛养殖的实际过程&#xff0c;提高他们的实践能力的教学方式。 VR技术开发公司广州华锐…

二十二、策略模式

目录 1、项目需求2、传统方案解决鸭子问题的分析和代码实现3、传统方式实现存在的问题分析和解决方案4、策略模式基本介绍5、使用策略模式解决鸭子问题6、策略模式的注意事项和细节7、策略模式的使用场景 以具体项目来演示为什么需要策略模式&#xff0c;策略模式的优点&#x…

如何快速的合并多个PPT使之成为一个PPT?

如何快速的合并多个PPT使之成为一个PPT&#xff1f; 项目过程中&#xff0c;经常给客户汇报&#xff0c;经常做PPT&#xff0c;有时候&#xff0c;需要把之前的ppt内容整合到新的内容中&#xff0c;如何快速合并以及使用呢&#xff1f; 幻灯片&#xff08;PPT中&#xff09;点…

SpringBoot3集成Kafka

标签&#xff1a;Kafka3.Kafka-eagle3&#xff1b; 一、简介 Kafka是一个开源的分布式事件流平台&#xff0c;常被用于高性能数据管道、流分析、数据集成和关键任务应用&#xff0c;基于Zookeeper协调的处理平台&#xff0c;也是一种消息系统&#xff0c;具有更好的吞吐量、内…

Python入门【动态添加属性和方法、正则表达式概述、match函数的使用、常用匹配符、限定符 、限定符使用示例】(二十九)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小王&#xff0c;CSDN博客博主,Python小白 &#x1f4d5;系列专栏&#xff1a;python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 &#x1f4e7;如果文章知识点有错误…

List Label Standard Reporting Edition Crack

List & Label Standard Reporting Edition Crack List&Label是适用于所有主要开发平台的报告解决方案&#xff0c;提供了强大的报告引擎、灵活的API和功能丰富的报告设计器。只需要几行代码就可以在桌面、web或云应用程序中嵌入List&Label。它允许您的应用程序用户…

Oracle字段长度不足位数补零

Oracle字段长度不足位数补零 有时候从数据库中取出的月份值是1&#xff0c;而不是01&#xff0c;该怎么办呢 SELECTLPAD( CODE_MONTH, 2, 0 ) FROMtb_cube_TY001 WHERECODE_BM_MEATYPE TY20 AND code_measure MYLX01 AND code_month <> ~ AND CODE_ENTITY 01A AND…

Spring框架中JavaBean的生命周期及单例模式与多列模式

Spring框架中JavaBean的生命周期及单例模式与多列模式 1. Spring框架中JavaBean的管理过程1.1 #定义Bean1.2 Bean的实例化1.3 属性注入1.4 初始化方法1.5 Bean的使用和引用1.6 销毁方法 2. 单例模式与原型模式在JavaBean管理中的应用1.在Spring管理JavaBean的过程中&#xff0c…

抖音短视频SEO矩阵系统源码开发

一、概述 抖音短视频SEO矩阵系统源码是一项综合技术&#xff0c;旨在帮助用户在抖音平台上创建并优化短视频内容。本文将详细介绍该系统的技术架构、核心代码、实现过程以及优化建议&#xff0c;以便读者更好地理解并应用这项技术。 二、技术架构 抖音短视频SEO矩阵系统采用前…

回归预测 | MATLAB实现TSO-BP金枪鱼群优化算法优化BP神经网络多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现TSO-BP金枪鱼群优化算法优化BP神经网络多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现TSO-BP金枪鱼群优化算法优化BP神经网络多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果…

机器学习|决策树:数学原理及代码解析

机器学习&#xff5c;决策树&#xff1a;数学原理及代码解析 决策树是一种常用的监督学习算法&#xff0c;适用于解决分类和回归问题。在本文中&#xff0c;我们将深入探讨决策树的数学原理&#xff0c;并提供 Python 示例代码帮助读者更好地理解和实现该算法。 决策树数学原…

3.若依前后端分离版开发用户自定义配置表格功能

一、背景 在项目上线测试的时候&#xff0c;关于同一个界面的表格&#xff0c;不同的用户会出现不同的字段排列需求&#xff0c;有些用户希望把A字段排在最前面&#xff0c;有些用户则希望A字段不显示。针对这种情况&#xff0c;开发一个表格自定义配置的功能&#xff0c;每个…

QT的核心——信号与槽

目录 回顾C 语言信号 1、信号与槽 2、关联信号与槽 2.1自动关联信号与槽 2.2手动关联信号与槽 2.3断开信号与槽 3、自定义信号 3.1自定义信号使用条件 3.2自定义槽函数使用条件 4、信号与槽参数传递 4.1自定义一个带参的信号 4.2关联带参的信号与槽 4.3发送一个带…

奥威BI数据可视化工具:个性化定制,打造独特大屏

每个人都有自己独特的审美&#xff0c;因此即使是做可视化大屏&#xff0c;也有很多人希望做出不一样的报表&#xff0c;用以缓解审美疲劳的同时提高报表浏览效率。因此这也催生出了数据可视化工具的个性化可视化大屏制作需求。 奥威BI数据可视化工具&#xff1a;个性化定制&a…

[线程/C++]线程同(异)步和原子变量

文章目录 1.线程的使用1.1 函数构造1.2 公共成员函数1.2.1 get_id()1.2.2 join()2.2.3 detach()2.2.5 joinable()2.2.6 operator 1.3 静态函数1.4 call_once 2. this_thread 命名空间2.1 get_id()2.2 sleep_for()2.3 sleep_until()2.4 yield() 3. 线程同步之互斥锁3.1 std:mute…

Open cv C++安装

注意;要退出conda的虚拟环境 依赖 1.更新系统 sudo apt-get update sudo apt-get upgrade 2.安装相关的依赖 sudo apt-get install build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev sudo apt-get install libjpeg-de…