Java【Spring】Bean 的作用域和生命周期

文章目录

  • 前言
  • 前言
  • 一、关于 Bean 的作用域问题引入
  • 二、Bean 的作用域
    • 1, 什么是 Bean 的作用域
    • 2, Bean 的六种作用域
    • 3, 设置 Bean 的作用域(解决开篇的问题)
  • 三、Bean 的生命周期
  • 总结


前言

前言

各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你:
JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等
Java数据结构: 顺序表, 链表, 堆, 二叉树, 二叉搜索树, 哈希表等
JavaEE初阶: 多线程, 网络编程, TCP/IP协议, HTTP协议, Tomcat, Servlet, Linux, JVM等(正在持续更新)

Bean 的作用域和生命周期是面试中很常见的问题, 就连字节, 百度等大厂也常考, 本文就介绍 Bean 的六种作用域, 和生命周期( 5 步执行流程)
在这里插入图片描述


提示:是正在努力进步的小菜鸟一只,如有大佬发现文章欠佳之处欢迎批评指点~ 废话不多说,直接上干货!


一、关于 Bean 的作用域问题引入

  • 定义一个 User 类(@Component注解), 作为公共的 Bean, 此类中仅需设置一个成员属性 name, 并给定值, 再提供 setter() 和 toString() 方法即可 :
    Java【Spring】Bean 的作用域和生命周期_第1张图片

  • 定义 UserComponent 类(@Component注解), 把上面的 User(公共Bean) 注入到当前类, 定义一个 run() 方法调用 User 类提供的 setter() 方法, 修改公共 Bean 的 name 属性
    Java【Spring】Bean 的作用域和生命周期_第2张图片

  • 定义 UserComponent2 类(@Component注解), 不对公共Bean 进行修改, 只是访问它, 查看它的 name 是什么
    Java【Spring】Bean 的作用域和生命周期_第3张图片

  • 在启动类中获取 UserComponent 和 UserComponent2 这两个 Bean, 分别调用 run() 方法
    Java【Spring】Bean 的作用域和生命周期_第4张图片

我们期望 : 对于公共的 Bean , UserComponent 在使用时修改了它, 而 UserComponent2 在使用公共 Bean 时, 不被 UserComponent 的行为所干扰
也就是说 : 原本 Bean 中的 name = “喜羊羊”, UserComponent 修改成了"沸羊羊", 我们希望 UserComponent2 访问公共 Bean 时看到的还是"喜羊羊"

  • 观察结果 :
    Java【Spring】Bean 的作用域和生命周期_第5张图片

为什么公共的 Bean 中的值被修改了? 那是不是意味着整个项目里, 一个 Bean 不应该被某个类访问并修改?

产生这种现象就是 Bean 的作用域导致的


二、Bean 的作用域

1, 什么是 Bean 的作用域

Bean 的作用域指的是Bean在整个 Spring 框架中的某个行为模式,比如 singleton 单例作用域表示 Bean 在整个 Spring 中只有一份,是全局共享的,当有一个用户修改了这个对象后,其他用户获取的就是这个修改后的对象

Bean 的作用域有 6 种:

  1. singleton:单例作用域

  2. prototype:原型作用域(也叫多例作用域)

  3. request:请求作用域

  4. session:会话作用域

  5. application:全局作用域

  6. websocket:HTTP WebSocket 作用域


2, Bean 的六种作用域

1, singleton:单例作用域

  • 该作用域下的 Bean 在 IoC 容器中只存在一个实例:获取 Bean(即通过applicationContext.getBean等方法获取)及装配Bean(即通过@Autowired注⼊)都是同一对象
  • 这是 Spring 默认的作用域
  • 通常是无状态的 Bean 使用的作用域 (无状态表示 Bean 对象的属性状态不需要修改)

2, prototype:原型作用域

  • 原型作用域也叫作多例作用域, 每次从 Spring 中获取 Bean 对象, 都会创建一份新的实例, @Autowired, @Resource 注入的对象以及 context 上下文 getBean 拿到的都是不同的 bean 对象
  • 通常是有状态的 Bean 使用的作用域 (有状态表示 Bean 对象的属性需要被修改)

3, request:请求作用域

  • 仅存在于 Spring MVC 中
  • 每一次 HTTP 请求都会创建新的实例, 类似于 prototype
  • 一次 HTTP 的请求和响应共享一个 bean

4, session:会话作用域

  • 仅存在于 Spring MVC 中
  • 在一个 HTTP session 中, 定义一个 Bean 实例

5, application:全局作用域

  • 仅存在于 Spring MVC 中
  • 在⼀个http servlet Context中,定义一个 Bean实例

6, websocket:HTTP WebSocket 作用域

  • 仅存在于 Spring MVC 中
  • 在一个 HTTP WebSocket 的生命周期中,定义一个 Bean 实例, WebSocket 的每次会话中,保存了一个 Map 结构的头信息,将用来包裹客户端消息头, 第一次初始化后,直到 WebSocket 结束都是同一个 Bean

3, 设置 Bean 的作用域(解决开篇的问题)

了解了 Bean 作用域, 我们知道, 在开篇引入的示例中, 由于 Bean 的默认作用域是 singleton, 如果改成 prototype , 那么在 UserComponent 和 UserComponent2 中, 注入 Bean 时就会创建一份新的实例, 哪怕有一万个类都是用这个 Bean 也不会互相干扰

声明 Bean 的作用域 : 使用 @Scope 注解

  • 使用方式1 : @Scope(“prototype”)
    Java【Spring】Bean 的作用域和生命周期_第6张图片
    Java【Spring】Bean 的作用域和生命周期_第7张图片

  • 使用方式2 : @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    Java【Spring】Bean 的作用域和生命周期_第8张图片
    Java【Spring】Bean 的作用域和生命周期_第9张图片

@Scope 可以加在类上, 配合类注解(@Controller、@Service、@Repository、@Component、@Configuration )使用
也可以加在方法上配合方法注解(@Bean)使用


三、Bean 的生命周期

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

Bean 的生命周期基本分为以下 5 步 :

  1. 实例化 Bean (开辟内存空间)

  2. 设置属性( Bean 注入)

  3. 初始化 Bean
    3.1, 执行实现了各种 Aware (通知)接口的方法
    3.2, 执行初始化的前置方法
    3.3, 执行初始化方法
    3.3, 执行初始化的后置方法

  4. 使用 Bean

  5. 销毁 Bean

Java【Spring】Bean 的作用域和生命周期_第10张图片

第二步和第三步的顺序能调换吗?(为什么要先注入再初始化?)
答案是否定的, 在第三步(初始化 Bean )时, 会执行各种各样的方法, 在这些方法中, 如果使用注入进来的 Bean, 但此时如果还没有把 Bean 注入进来, 还怎么使用? 可想而知会产生异常, 所以是先注入 Bean , 再进行初始化 Bean


总结

以上就是本篇的所有内容了, 如果本篇对你有帮助,请点赞收藏支持一下,小手一抖就是对作者莫大的鼓励啦~


上山总比下山辛苦
下篇文章见

Java【Spring】Bean 的作用域和生命周期_第11张图片

你可能感兴趣的:(JavaEE进阶,java,spring,Bean,作用域,生命周期)