当前位置: 首页 > news >正文

【Spring】什么是Bean的生命周期及作用域,什么是Spring的执行流程?

                         

  • 博主简介:想进大厂的打工人
  • 博主主页:@xyk:
  • 所属专栏: JavaEE进阶 

在前面的播客中讲解了如何从Spring中存取Bean对象,那么本篇我们来讲解Bean对象的生命周期是什么,Bean对象的6种作用域分别是什么,都有哪些区别,还有Spring容器的是如何启动并执行的,请看下文~~


目录

一、Bean作用域问题案例

二、Bean的作用域

2.1 Bean的6种作用域

2.2 Spring中如何设置作用域

三、Spring的执行流程

四、Bean的生命周期

4.1  Bean 实例化与 Bean 初始化的区别?

4.2 为什么先设置属性而后再初始化?


一、Bean作用域问题案例

首先,我们创建一个 Student 类,作为 Bean。通过 StudentBeans 类中的 student 配合 @Bean 注解存储 Bean。而后,StudentController 依次先访问 Bean 后对其进行修改。

最后,通过 StudentAdviceController 再次访问 Bean。观察 StudentController2 访问的 Bean 是否为 StudentController 修改 Bean 之前的值。

 预期结果: 我们希望 公共 Bean 可以在各⾃的类中被修改,但不影响到其他类,然而(说好⼀起到⽩头,你却悄悄焗了油)

StudentBeans

@Component
public class StudentBeans {@Beanpublic Student student1() {// 伪代码,构建对象Student stu = new Student();stu.setId(1);stu.setName("张三");stu.setAge(18);return stu;}
}

StudentController

@Controller
public class StudentController {@Autowiredprivate Student student;public void printStudent(){System.out.println(student);Student student1 = this.student;student1.setName("李四");System.out.println(student);}
}

StudentController2

@Controller
public class StudentController2 {@Autowiredprivate Student student;public void printStudent(){System.out.println(student);}
}

main方法

public class App {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");StudentController student = context.getBean("studentController",StudentController.class);student.printStudent();StudentController2 student2 = context.getBean("studentController2",StudentController2.class);student2.printStudent();}
}

预期结果:

可见,studentController 对 Bean 修改后,studentController2 访问的是修改后的 Bean,这与预期不符。为了达到预期,我们还需要了解 Spring 中 Bean 的作用域~

原因分析:

操作以上问题的原因是因为 Bean 默认情况下是单例状态(singleton),也就是所有⼈的使⽤的都是同⼀个对象,之前我们学单例模式的时候都知道,使⽤单例可以很⼤程度上提⾼性能,所以在 Spring 中Bean 的作⽤域默认也是 singleton 单例模式

二、Bean的作用域

2.1 Bean的6种作用域

作用域定义:

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

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

singleton:单例作⽤域:该作⽤域下的Bean在IoC容器中只存在⼀个实例,通常⽆状态的Bean使⽤该作⽤域。⽆状态表示Bean对象的属性状态不需要更新。Spring默认选择该作⽤域!

prototype:原型作⽤域(多例作⽤域):每次对该作⽤域下的Bean的请求都会创建新的实例,通常有状态的Bean使⽤该作⽤域

request:请求作⽤域:每次http请求会创建新的Bean实例,类似于prototype,⼀次http的请求和响应的共享Bean

session:回话作⽤域:在⼀个http session中,定义⼀个Bean实例;⽤户回话的共享Bean, ⽐如:记录⼀个⽤户的登陆信息

application:全局作⽤域:在⼀个http servlet Context中,定义⼀个Bean实例,Web应⽤的上下⽂信息,⽐如:记录⼀个应⽤的共享信息

websocket:HTTP WebSocket 作⽤域:在⼀个HTTP WebSocket的⽣命周期中,定义⼀个Bean实例;WebSocket的每次会话中,保存了⼀个Map结构的头信息,将⽤来包裹客户端消息头。第⼀
次初始化后,直到WebSocket结束都是同⼀个Bean
 

单例作用域与全局作用域的区别?

单例作用域意味着在容器中,每一个Bean只会被创建一次,并且所有的请求都会返回同一实例。而全局作用域与单例作用域不同,在全局作用域下,Bean 被创建一次后,会在整个应用程序的上下文中共享使用,即每一个请求返回的都是同一个实例。

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

2.2 Spring中如何设置作用域

我们可以使用 @Scope 标签来声明 Bean 的作⽤域。
@Scope 标签既可以修饰⽅法也可以修饰类,并且,有两种设置⽅式。这里以设置作用域为 prototype 为例:

  1. 直接设置值:@Scope(“prototype”)
  2. 使⽤枚举设置:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

我们将上面的例子中的作用域进行修改,就不会出现只有一个Bean实例的情况了

@Component
public class StudentBeans {@Scope("prototype")
//    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)@Beanpublic Student student1() {// 伪代码,构建对象Student stu = new Student();stu.setId(1);stu.setName("张三");stu.setAge(18);return stu;}
}

三、Spring的执行流程

Spring 的执行流程大致如下:
启动 Spring 容器 -> 根据配置完成 Bean 的初始化 -> Bean 注册到 Spring 容器中(存操作) -> 将 Bean 装配到需要的类中(取操作)Spring 的执行流程大致如下:

四、Bean的生命周期

生命周期指的是 一个对象从创建到销毁的全过程~,这里所说的 Bean 的生命周期,是指 Bean 从创建到使用再到销毁的完整过程。Bean 的⽣命周期分为以下 5 ⼤部分:

  1. 实例化(对应JVM中的“加载”):从无到有,将字节码转换成内存中的对象,只是分配了内存  eg:买了一套毛坯房
  2. 设置属性(Bean注入和装配) eg:购买装修材料(引入外部资源)
  3. 初始化  eg:对房子的装修                                                                                                         a)各种通知  eg:打电话给各个装修的师傅来施工                                                                     b)初始化的前置工作  eg:师傅达到现场,先勘察环境,制定装修方案,比如测量房子的面积等~                                                                                                                                           c)进行初始化工作(两种方式:注解或者xml。使用注解@PostConstruct 初始化、使用(xml) init-method 初始化) eg:两类师傅进行装修:水工、瓦工、电工等。
  4. 使用Bean  eg:房子可以住人了
  5. 销毁Bean  eg:卖房

 

4.1  Bean 实例化与 Bean 初始化的区别?

Bean 实例化和 Bean 初始化都是 Spring 容器处理 Bean 生命周期中的不同阶段。

  • Bean实例化是指为Bean分配内存空间,即根据配置文件将Bean对象创建出来并且存入到容器中管理,这个过程包括实例化Bean,调用构造函数,注入依赖等
  • Bean初始化是指在Bean对象创建完成之后,Spring容器调用特定的方法进行对Bean进行初始化配置的过程,可以为 Bean 配置一些属性、调用一些初始化方法等。
  • 比如使用@PostConstruct@PreDestroy注解等

4.2 为什么先设置属性而后再初始化?

在 Bean 的生命周期中,先设置属性再初始化,是因为在 Spring IoC 容器中,Bean 的创建和初始化分为两个阶段,即 Bean 的实例化和属性注入阶段,和 Bean 的初始化阶段。在实例化阶段,Spring IoC 容器会先创建 Bean 的实例对象,但此时 Bean 的属性还未被注入。接着,Spring IoC 容器调用 Bean 的 set 方法注入属性值。当所有属性都被注入后,Spring IoC 容器才会执行 Bean 的初始化方法。因此,先设置属性而后再初始化。

如果顺序反过来进行设置,会发生空指针异常!!

http://www.lryc.cn/news/99874.html

相关文章:

  • 立创EDA学习
  • 清风学习笔记—层次分析法—matlab对判断矩阵的一致性检验
  • 大众安徽内推
  • Meta “地平线世界”移动端应用即将上线,手机快乐元宇宙?
  • 更省更快更安全的云服务器,一站式集中管理,随时随地远程——站斧云桌面
  • 出现 Try run Maven import with -U flag (force update snapshots) 的解决方法
  • python多线程
  • Spring Framework 提供缓存管理器Caffeine
  • ZQC的游戏 题解
  • 24考研数据结构-第一章 绪论
  • Gitlab 备份与恢复
  • 数据库—用户权限管理(三十三)
  • C语言【怎么定义变量?】
  • vue中使用vab-magnifier实现放大镜效果
  • 无涯教程-jQuery - Highlight方法函数
  • 【bar堆叠图形绘制】
  • ORACLE数据库灾难恢复
  • base和正则备份
  • ArcGIS Engine 与 Visual Studio版本对照表
  • JPA连接达梦数据库导致auto-ddl失效问题解决
  • 【MATLAB第60期】【更新中】基于MATLAB的ARMAX具有外生回归因子的移动平均自回归模型
  • Vue 常用指令 v-on 自定义参数,事件修饰符
  • 重要通知|关于JumpServer开源堡垒机V2版本产品生命周期的相关说明
  • 下载快 kaggle output
  • 结构型设计模式-1.代理设计模式
  • Python(四十九)获取列表指定元素的索引
  • 年轻人的第一套海景房
  • Vue输入内容/链接生成二维码
  • 使用langchain与你自己的数据对话(二):向量存储与嵌入
  • No105.精选前端面试题,享受每天的挑战和学习