Spring的主要作用就是读取和存储Bean。本篇我们讲深入学习Bean对象。
一、Bean作用域
先来看个问题:
有⼀个公共的 UserBean,提供给 B ⽤户和 C ⽤户使⽤,然⽽在使⽤的途中 B ⽤户却“ 悄悄” 地修 改了公共 Bean 的数据,导致 C ⽤户在使⽤时发⽣错误。
公共Bean
B写的UserController
C写的UserAdviceController
运行
发现B在自己的类中修改了Bean但会影响到C的类。
造成这种情况的原因是因为Bean默认的是单例模式。单例模式中所有类使用的都是同一个对象。
1.1、作用域
限定程序中变量的可⽤范围叫做作⽤域。
⽽ Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种⾏为模式,⽐如 singleton 单例作⽤域,就 表示 Bean 在整个 Spring 中只有⼀份,它是全局共享的,那么当其他⼈修改了这个值之后,那么另⼀ 个⼈读取到的就是被修改的值。
Bean的6种作用域:
1)singleton: 单例模式 (默认,每次请求取的是同一个对象。)
2)prototype: 原型模式 (多例模式,每次请求创建一个新的对象)
3)request: 请求作用域 (Spring MVC,每次http请求创建一个对象)
4)session: 会话作用域 (Spring MVC,在一个会话中共享一个对象)
5)application: 全局作用域 (Spring MVC,所有人共用一个)
6)websocket: HTTP WebSocket 作用域 (Spring WebSocket 项目中存在的一种)
1.2、设置Bean的作用域
使⽤ @Scope 标签就可以⽤来声明 Bean 的作⽤域
@Scope 标签既可以修饰⽅法也可以修饰类。
@Scope 有两种设置⽅式:
1. 直接设置值: @Scope("prototype")
2.全局变量的方式设置:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
在公共Bean中设置作用域后,可以看到和预期结果一样了。
二、Bean的生命周期
2.1、Spring的执行流程
1、启动容器
2、读取配置文件,初始化
a)使用xml注册bean
b)配置bean根(扫描)路径
3、将bean存储到Spring中,通过类注解进行扫描和装配
4、将bean从spring读取出来,装配到相应的类
2.2、Bean的生命周期:
1.实例化(对应 JVM 中的“加载”)【从无到有,将字节码转换成内存中的对象,只是分配了内存】 ex:买了一套毛坯房
2.设置属性(Bean 注入和装配)
ex:购买装修材料(引入外部资源)
3.Bean初始化
ex:房子装修
a)各种通知
ex:打电话给各个装修的师傅来施工(水工、电工、瓦工...)
b)初始化的前置工作
ex:师傅达到现场,先勘察环境,制定装修方案【前置工作】
c)进行初始化工作【使用注解 @PostConstruct初始化、使用(xml)init-method 初始化】
ex:两类师傅进行装修,技术好的,技术一般
d)初始化的后置工作
ex:装修之后的清理工作
4.使用 Bean
ex:房子可以入住使用了
5.销毁 Bean
ex:卖掉这套房