Bean 作用域和生命周期 · Bean 作用域存在的问题 · Bean 六种作用域 · 执行流程 · 生命周期演示

news2024/11/21 1:32:13

Spring 是用来存储和读取 Bean,因此 Spring 中 Bean 是最核心的操作资源,我们需要深入学习一下 Bean 对象。

  • 一、Bean 的作用域问题
    • 1.1 原因分析
    • 1.2 作用域定义
  • 二、Bean 的六种作用域
    • singleton 单例作用域
    • prototype 原型作用域
    • request 请求作用域
    • session 回话作用域
    • application 全局作用域
    • websocket(HTTP WebSocket作用域)
    • 单例作用域(singleton)和全局作用域(application)的区别。
  • 三、Bean 原理分析
    • 3.1 Bean 执行流程
    • 3.2 Bean 执行流程小结(Spring 执行流程)
    • 3.3 Bean 生命周期
  • 四、Bean 生命周期演示

一、Bean 的作用域问题

通过一个案例来看 Bean 作用域的问题

假设现在有一个公共的 Bean,提供给 A 用户和 B 用户使用,然鹅在使用的途中 A 用户偷偷修改了公共 Bean 的数据,导致 B 用户在使用的时候发生了预期之外的逻辑错误。

公共 Bean:

@Component
public class Users {
    @Bean
    public User user1(){
        User user = new User();
        user.setId(1);
        user.setName("Java");
        return user;
    }
}

A 用户在使用的时候,进行修改:

@Controller
public class BeanScopesController {
    @Autowired
    private User user1;

    public User getUser1(){
        User user = user1;
        System.out.println("bean原name:" + user.getName());
        user.setName("零一");
        return user;
    }
}

B 用户再去使用公共 Bean 的时候:

@Controller
public class BeanScopesController2 {
    @Autowired
    private User user1;

    public User getUser1(){
        User user = user1;
        return user;
    }
}

打印 A 用户和 B 用户公共 Bean 的值:

public class BeansScopesTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        BeanScopesController bsc = context.getBean(BeanScopesController.class);
        System.out.println("a修改之后" + bsc.getUser1().toString());

        BeanScopesController2 bsc2 = context.getBean(BeanScopesController2.class);
        System.out.println("b读取到的name" + bsc2.getUser1().toString());
    }
}

执行结果如下:

1.1 原因分析

操作以上问题的原因是:Bean 默认情况下是单例状态(singleton),也就是所有人使用的都是同一个对象。
使用单例可以很大程度上提高性能,所以在 Spring 中 Bean 的作用域默认也是 singleton 单例模式。

1.2 作用域定义

限定程序中变量的可用范围叫做作用域,或者说在源代码中定义变量的某个区域叫做作用域。

而 Bean 的作用域是指 Bean 在 Spring 整个框架中的某种行为模式,比如 singleton 单例作用域,就表示 Bean 在整个 Spring 中只有一份,它是全局共享的,那么当其他人修改了这个值之后,那么另一个读取到就是被修改的值。



二、Bean 的六种作用域

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

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

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

singleton 单例作用域

  • 描述:该作用域下的 Bean 在 IoC 容器中只存在一个实例,获取 Bean(通过 applicationContext.getBean 等方法获取)以及装配 Bean(通过 @Autowired 注入)都是同一个对象。
  • 使用场景:通常无状态的 Bean 使用该作用域,无状态表示 Bean 对象的属性状态不需要更新。
  • 备注:Spring 默认选择该作用域。

prototype 原型作用域

  • 描述:每次对该作用域下的 Bean 的请求都会创建新的实例。获取Bean(通过 applicationContext.getBean 等方法获取)以及装配 Bean(通过 @Autowired 注入)都是新的对象实例。
  • 场景:通常有状态的 Bean 使用该作用域。

request 请求作用域

  • 描述:每次 http 请求会创建新的 Bean 实例,类似于 prototype.
  • 场景:一次 http 的请求和响应都共享 Bean。
  • 备注:限定 SpringMVC 中使用。

session 回话作用域

  • 描述:在一个 http session中,定义一个 Bean 实例。
  • 场景:用户回话的共享 Bean,比如记录一个用户的登录信息。
  • 备注:限定 SpringMVC 中使用。

application 全局作用域

  • 描述:在一个 http servlet Context 中,定义一个 Bean 实例。
  • 场景:Web 应用的上下文信息,比如记录一个应用的共享信息。
  • 备注:限定 SpringMVC 中使用。

websocket(HTTP WebSocket作用域)

  • 描述:在一个 HTTP WebSocket 的生命周期中,定义一个 Bean 实例。
  • 场景:WebSocket 的每次会话中,保存了一个 Map 结构的头信息,将用来包裹客户端信息头。第一次初始化后,直到 WebSocket 结束都是同一个 Bean。
  • 备注:限定 SpringMVC 中使用。

单例作用域(singleton)和全局作用域(application)的区别。

  • singleton 是 Spring Core 的作用域;application 是 Spring Web 中的作用域;
  • singleton 作用于 IoC 的容器,而 application 作用于 Servlet 容器。


三、Bean 原理分析

3.1 Bean 执行流程

启动容器:
加载配置文件。

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

根据配置完成 Bean 初始化:
扫描 com.bit.service 包下边的 Spring 注解(@Controller、@Service、@Component、@Repository)。

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

    <content:component-scan base-package="com.bit.service">
    </content:component-scan>

</beans>

注册 Bean 对象到容器中:

@Component
public class UComponent {

}
@Controller
public class UserController {

}
@Repository
public class UserRepository {

}

装配 Bean 的属性:
如果 Bean 对象需要使用其它 Bean 对象作为属性,可以使用注解 @Autowired、@Resource.

@Controller
public class UserController {

    @Autowired
    private UserService userService;
}

3.2 Bean 执行流程小结(Spring 执行流程)

①启动 Spring 容器 -> ②实例化 Bean(分配内存空间,从无到有) -> ③Bean 注册到 Spring 中(存储操作)-> ④将 Bean 装配到需要的类中(取操作)。


3.3 Bean 生命周期

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

Bean 的生命周期分为以下五大部分:

1. 实例化 Bean(为 Bean 分配内存空间)
2. 设置属性(Bean 注入和装配)
3. Bean 初始化
	① 实现了各种 Aware 通知的方法,如 BeanNameAware、BeanFactoryAware、ApplicationContextAware 的接口方法;
	② 执行 BeanPostProcessor 初始化前置方法;
	③ 执行 @PostConstruct 初始化方法,依赖注入操作之后被执行;
	④ 执行自己指定的 init-method 方法(如果有指定的话);
	⑤ 执行 BeanPostProcessor 初始化后置方法。
4. 使用 Bean
5. 销毁 Bean


实例化和初始化的区别

实例化和属性设置是 Java 级别的系统 “事件”,其操作过程不可人工干预和修改;而初始化是给开发者提供的看,可以在实例化之后,类加载完成之前进行自定义 “事件” 处理。


生命流程的 “故事”

Bean 的生命流程看似复杂,但我们可以使用生活中的例子来理解它。

假设我们现在需要买房子,那么我们的流程是这样的:

  1. 先买房(实例化,从无到有);
  2. 装修(设置属性);
  3. 买家电,如洗衣机、冰箱、电视、空调等(各种 初始化);
  4. 入住(使用 Bean);
  5. 卖出去(Bean 销毁)。


四、Bean 生命周期演示

@Component
public class BeanLifeComponent implements BeanNameAware {
    @PostConstruct
    public void postConstruce() {
        System.out.println("执行了 postConstruce 方法");
    }

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

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

    public void setBeanName(String s) {
        System.out.println("执行了 setBeanName 方法" + s);
    }
}

xml 配置文件:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
    <content:component-scan base-package="com.bit">
    </content:component-scan>

    <beans>
        <bean id="beanLifeComponent" class="com.bit.service.BeanLifeComponent" init-method="init"></bean>
    </beans>
</beans>

测试方法:

public class BeanListTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        BeanLifeComponent bean = context.getBean(BeanLifeComponent.class);
        System.out.println("执行 main 方法");
        context.destroy();
    }
}

代码执行结果:

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

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

相关文章

【OpenCV学习】第16课:图像边缘提取 - Sobel算子详细剖析(图像梯度)

仅自学做笔记用,后续有错误会更改 理论 卷积的应用 - 图像边缘提取&#xff1a; 边缘是什么&#xff1a;是像素值发生跃迁的地方&#xff0c; 是图像的显著特征之一&#xff0c; 再图像特征提取丶对象检测丶模式识别等方面都有重要作用如何捕捉/提取边缘&#xff1a;对图像求…

关于LuaGC算法的演化概述

2年不用&#xff0c;就忘了&#xff0c;在这记录下。 5.0版本的双色标记清除算法 此算法中&#xff0c;每个对象会有两种标记态&#xff1a;白色和黑色&#xff1b;新创建的对象都是白色 过程&#xff1a; 1.初始化阶段&#xff1a;将root链表中的所有对象放入待检链表中&am…

0204隐函数及由参数方程所确定的函数的导数相关变化率-导数与微分

1 隐函数 定义&#xff1a;设有两个非空数集A,BA,BA,B.对于∀x∈A\forall x\in A∀x∈A&#xff0c;由二元方程F(x,y)0F(x,y)0F(x,y)0对应唯一的y∈By\in By∈B,称此对应关系是二元方程F(X,y)0F(X,y)0F(X,y)0确定的隐函数。 相应的由yf(x)yf(x)yf(x)确定的对应关系称为显函数。…

vue.js:作用域插槽的使用案例

作用域插槽的使用理解 父组件替换插槽的标签&#xff0c;但是内容是由子组件提供的。 案例需求 子组件中包含一组数据&#xff0c;比如&#xff1a;pLanguages&#xff1a;[‘Java’,‘c’,‘JavaScript’,‘python’,‘C语言’,‘Go’,‘C#’]现需要在多个页面进行操作&…

19.8 适配器概念、分类、范例与总结

一&#xff1a;适配器基本概念 把一个既有的东西进行适当的改造&#xff0c;比如增加点东西&#xff0c;或者减少点东西&#xff0c;就构成了一个适配器。 三种适配器&#xff1a;容器适配器、算法适配器、迭代适配器。 二&#xff1a;容器适配器 本章第三节学习过双端队列de…

个人有效:关于VMware虚拟机开机蓝屏问题的解决

文章目录前言禁用Hyper-V等服务Device 服务等启动相关是否需要VMware最新版本电脑虚拟化问题启用或关闭windows功能的设置关于VMware虚拟机的卸载参考前言 搜了海量文章&#xff0c;实操过大部分的方法&#xff0c;一顿折腾、最后莫名其妙的能跑了…。~~两天来急痛攻心&#xf…

Hot100-寻找重复数

1 前言 给定一个包含 n 1 个整数的数组 nums &#xff0c;其数字都在 [1, n] 范围内&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 &#xff0c;返回 这个重复的数 。 1.1 暴力解法 两次for循环&#xff1a…

spring——AOP面向切面编程—— 一般切面的 AOP 开发

一般切面的 AOP 开发 当我们在使用 Spring AOP 开发时&#xff0c;若没有对切面进行具体定义&#xff0c;Spring AOP 会通过 Advisor 为我们定义一个一般切面(不带切点的切面)&#xff0c;然后对目标对象(Target)中的所有方法连接点进行拦截&#xff0c;并织入增强代码。 工程依…

Pytest----测试脚本上传git代码仓库

【原文链接】Pytest----测试脚本上传git代码仓库 在企业实战中&#xff0c;自动化测试脚本也要放在代码管理平台的&#xff0c;可以选择第三方公共的git代码托管平台&#xff0c;比如github、gitee等&#xff0c;当然也可以在企业内部搭建gitlab作为代码托管平台&#xff0c;他…

蓝桥杯模拟赛习题练习(一)

题目来源&#xff1a;第十四届蓝桥杯模拟赛第一期 注&#xff1a;代码都是自己写的&#xff0c;不是参考答案&#xff01; 1. 二进制位数 问题描述&#xff1a; 十进制整数2在十进制中是1位数&#xff0c;在二进制中对应10 &#xff0c;是2位数。 十进制整数22在十进制中是2位…

Linux系统调用实现简析

1. 前言 限于作者能力水平&#xff0c;本文可能存在的谬误&#xff0c;因此而给读者带来的损失&#xff0c;作者不做任何承诺。 2. 背景 本篇基于 Linux 4.14 ARM 32 glibc-2.31 进行分析。 3. 系统调用的实现 3.1 系统调用的发起 3.1.1 起于用户空间 我们随意挑选一个…

python学习之:妙用魔法函数 __dict___来调用对象中的方法,或者 python文件中的方法

文章目录场景原始写法升级写法面向对象的写法总结场景 原始写法 假设现在有一个文件 tool.py我想在外部输入一个 字符串 就调用这个字符串对应的函数如果你不是用 __dict__ 这个好用的函数&#xff0c;那么你大概率会以下面的方式去写 main 函数&#xff0c;给很多 if但是如果…

网络安全观察报告 态势总览

执行摘要 从 1987 年 9 月 14 日&#xff0c;中国向世界发出第一封电子邮件 到如今&#xff0c;中国的互联网发展已过去整整 31 个年头。从消费互联、产业互联到万物互联&#xff0c;互联网正在加速改变我们的交流方式和交易方式&#xff0c;一次次 004.重塑了国家的经济形态和…

创建型 - 单例模式(Singleton pattern)

单例模式&#xff08;Singleton Pattern&#xff09;&#xff1a;确保一个类有且只有一个实例&#xff0c;并提供一个全局访问点。 文章目录懒汉式-线程不安全饿汉式-线程安全懒汉式-线程安全双重校验锁-线程安全静态内部类实现枚举实现实现方式总结使用场景JDK懒汉式-线程不安…

论文(world、WPS)插入参考文献引用详细教程

一、参考资料 如何在WPS中添加论文参考文献 【Word】怎样给论文添加引用参考文献 word添加各种引用 二、相关介绍 1. 参考文献的标注 参考文献的标注分为全部引用、局部引用、间接引用。 1.1 全部引用&#xff08;直接引用&#xff09; 需要双引号&#xff0c;无论冒号…

[附源码]Python计算机毕业设计SSM基于的社区疫情管理系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

ADI Blackfin DSP处理器-BF533的开发详解24:触摸屏的实现和应用(含源代码)

硬件准备** ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 使用到硬件模块原理图 功能介绍 四线电阻式触摸屏&#xff0c;拿笔和指甲划拉的&#xff0c;不是现在的容性触摸屏。 ADSP-EDU-BF53x 板卡的 …

《Docker》阿里云服务器docker部署nginx并配置https踩坑记录(完整)

前端博主&#xff0c;热衷各种前端向的骚操作&#xff0c;经常想到哪就写到哪&#xff0c;如果有感兴趣的技术和前端效果可以留言&#xff5e;博主看到后会去代替大家踩坑的&#xff5e; 主页: oliver尹的主页 格言: 跌倒了爬起来就好&#xff5e; 来个关注吧&#xff0c;点个赞…

# Docker说明、安装(Windows10家庭版)

Docker说明、安装&#xff08;Windows10家庭版&#xff09; Docker是什么&#xff1f;它是干嘛的&#xff1f; 开始&#xff0c;我就知道别人说是用来加工tar包的。tar包&#xff1f;又是干什么用的&#xff1f; tar包&#xff0c;个人粗俗的理解就是一个环境&#xff0c;里面…

CVPR2021 | VQGAN+:Taming Transformers for High-Resolution Image Synthesis

原文标题&#xff1a;Taming Transformers for High-Resolution Image Synthesis 主页&#xff1a;Taming Transformers for High-Resolution Image Synthesis 代码&#xff1a;https://github.com/CompVis/taming-transformers transformer比CNN缺少了归纳偏置和局部性&…