文章目录
- 前言
- 前言
- 一、关于 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() 方法即可 :
-
定义 UserComponent 类
(@Component注解)
, 把上面的 User(公共Bean) 注入到当前类, 定义一个 run() 方法调用 User 类提供的 setter() 方法, 修改公共 Bean 的 name 属性
-
定义 UserComponent2 类
(@Component注解)
, 不对公共Bean 进行修改, 只是访问它, 查看它的 name 是什么
-
在启动类中获取 UserComponent 和 UserComponent2 这两个 Bean, 分别调用 run() 方法
我们期望 : 对于公共的 Bean , UserComponent 在使用时修改了它, 而 UserComponent2 在使用公共 Bean 时, 不被 UserComponent 的行为所干扰
也就是说 : 原本 Bean 中的 name = “喜羊羊”, UserComponent 修改成了"沸羊羊", 我们希望 UserComponent2 访问公共 Bean 时看到的还是"喜羊羊"
- 观察结果 :
为什么公共的 Bean 中的值被修改了? 那是不是意味着整个项目里, 一个 Bean 不应该被某个类访问并修改?
产生这种现象就是 Bean 的作用域导致的
二、Bean 的作用域
1, 什么是 Bean 的作用域
Bean 的作用域指的是Bean在整个 Spring 框架中的某个行为模式,比如 singleton 单例作用域
表示 Bean 在整个 Spring 中只有一份,是全局共享的,当有一个用户修改了这个对象后,其他用户获取的就是这个修改后的对象
Bean 的作用域有 6 种:
-
singleton:单例作用域
-
prototype:原型作用域(也叫多例作用域)
-
request:请求作用域
-
session:会话作用域
-
application:全局作用域
-
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”)
-
使用方式2 : @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Scope 可以加在类上, 配合类注解
(@Controller、@Service、@Repository、@Component、@Configuration )
使用
也可以加在方法上配合方法注解(@Bean)
使用
三、Bean 的生命周期
所谓的生命周期指的是一个对象从诞生到销毁的整个生命过程, 我们把这个过程就叫做一个对象的生命周期, Bean 的生命周期就是 Bean 从诞生到销毁的过程
Bean 的生命周期基本分为以下 5 步 :
-
实例化 Bean (开辟内存空间)
-
设置属性( Bean 注入)
-
初始化 Bean
3.1, 执行实现了各种 Aware (通知)接口的方法
3.2, 执行初始化的前置方法
3.3, 执行初始化方法
3.3, 执行初始化的后置方法 -
使用 Bean
-
销毁 Bean
第二步和第三步的顺序能调换吗?(为什么要先注入再初始化?)
答案是否定的, 在第三步(初始化 Bean )时, 会执行各种各样的方法, 在这些方法中, 如果使用注入进来的 Bean, 但此时如果还没有把 Bean 注入进来, 还怎么使用? 可想而知会产生异常, 所以是先注入 Bean , 再进行初始化 Bean
总结
以上就是本篇的所有内容了, 如果本篇对你有帮助,请点赞收藏支持一下,小手一抖就是对作者莫大的鼓励啦😋😋😋~
上山总比下山辛苦
下篇文章见