您现在的位置是:首页 >学无止境 >Bean作用域与生命周期网站首页学无止境
Bean作用域与生命周期
日升时奋斗,日落时自省
目录
如果没有基本的Sping操作Maven的基础,可以先看一下下面的两篇博客
此处相关的Bean作用域问题,来看Bean的作用域是怎么样的(我们从问题开始解析一个概念)
两个用户获取同一个对象对一个Bean对象进行修改或者查看,如果一个用户对Bean对象进行修改后,这个公共对象就会被修改,另一个用户访问接收到的信息就是更改后的,但是两个用户应该是不相重复的(就是你操作你的,我操作我的,互不影响)
1、Bean的作用域问题
注:以上需要的这些前置操作的依赖,和配置文件都可以去前面的博客自取
1.1、Lombok
首先要先写一个用户吧,这里不白写,给友友们在介绍一个注解Lombok(以下有详细操作,需要下载一个插件)
Lombok插件下载好了,引入依赖到pom.xml文件中的dependencies标签中
以上需要的操作都结束了,现在来创建一个实体类来使用Lombok中的注解(现在没有写获取属性的操作,一会bean对象获取就会进行此操作)
1.2、修改Bean对象
经过对象注入以后,两个Controllerle类就已经获取到了Bean对象了(相当于两个用户拿到了自己的页面,应该是各自操作各自的,互不影响)
接下来,我们写一下启动类,来看看是否会有我们想要的结果
注:Bean作用域是Bean在Spring整个框架中的某种行为模式,比如当前使用的模式就是singleton单例作用域,Bean对象在Spring中只有一份,作用域全局,所有类都可以获取使用,其他人修改也就改变了(singleton也是Spring默认的行为模式)
2、作用域定义
作用域(scope)指的是在编程中,一段代码中变量、函数、对象等可被访问的范围。在不同的编程语言中,作用域的定义可能会有所不同,但是通常都是通过块级作用域或函数级作用域来实现的。作用域可以分为全局作用域和局部作用域,全局作用域中的变量可以在整个程序中被访问,而局部作用域中的变量只能在其定义的范围内被访问。
2.1、Bean的6种作用域
Spring容器在初始化一个Bean的实例时,同时会指定该实例的作用域,Spring有6种作用域
<1>singleton:单例作用域
<2>prototype:原型作用域(多例作用域)
<3>request:请求作用域
<4>session:会话作用域
<5>application:全局作用域
<6>websocket:HTTPWebSocket作用域
注:前两种作用域是针对普通的Spring项目,后4种针对SpringMVC
2.1.1、singleton
描述:在Spring IoC容器中的bean作用域,整个应用程序上下文中只有一个实例对象存在,整个应用程序上下文中只有一个实例对象存在,可以保证不同模块间使用的是同一个实例对象,提高程序的性能和效率
场景:通常无状态的Bean使用该作用域,无状态表示Bean对象的属性不需要更新
使用:Spring默认选择作用域
2.1.2、prototype
描述:Prototype是一种在Spring IoC容器中定义的bean作用域,它表示每次请求获取该bean时都会创建一个新的实例对象。也就是说,每次调用getBean()方法时,都会返回一个新的实例对象。
场景:Prototype作用域适用于需要频繁创建和销毁的对象,而且不需要共享状态的场景,通常有状态的Bean使用该作用域
使用:作用域普通的Spring中
2.1.3、request
描述:在Spring中,Bean定义为request作用域,表示该Bean只在当前HTTP请求中有效。这意味着,每次HTTP请求都会创建一个新的Bean实例,并且该实例仅在当前请求中有效。(类似于prototype)
场景:一次http的请求和响应的共享Bean,
使用:限定于SpringMVC中使用
2.1.4、session
描述:在Spring中,Bean定义为Session作用域,表示该Bean的生命周期与Web应用程序的Session周期相同。每个Session都会对应一个Session作用域的Bean实例,而且该实例在整个Session中都有效。
场景:Web应用的上下文信息,例如:一个登录信息(就是我们之前使用的Session)
使用:限定与SpringMVC中使用
2.1.5、appliction(了解)
描述:在http Servlet Context中定义一个Bean实例
场景:Web应用的上下文信息,例如:一个共享信息(独一份的)
使用:限定SpringMVC中使用
注:Application作用域的Bean实例在整个应用程序期间都有效,因此需要考虑线程安全的问题。另外,Application作用域的Bean实例占用内存较多,不适合用于保存大量数据或长时间运行的任务
2.1.6、websocket(了解)
描述:在一个http WebSocket的生命周期中,定义一个Bean实例
场景:Spring中没有WebSocket作用域,WebSocket是一种协议,用于在客户端和服务器之间建立双向通信通道。在Spring中,我们可以使用WebSocket来实现实时通信、推送消息等功能,但是并不存在WebSocket作用域的概念
使用:限定Spring webSocket中使用
2.2、设置作用域
刚刚写了两个用户,但是Spring作用域默认我是singleton单例作用域,现在设置作用域将每个用户的作用操作
作用域更稳定的设置方法: 使用Spring自己提供的参数,我们手敲情况还是比较容易出错的
3、Spring执行流程和Bean的生命周求
3.1、Spring执行流程
3.2、Bean生命周期
生命周期是指一个事物在一定时间内经历的各个阶段或状态,所以Bean的生命周期就可以分为以下5个部分(也就是五个阶段,每个状态对应不同的状态)
<1>实例化Bean
过程:Spring会根据配置文件中的信息创建Bean的实例,为Bean对象分配内存空间
<2>设置属性
过程:Spring会将Bean的属性值设定到Bean实例中。属性值可以通过构造函数参数或者setter方法注入(对象注入)
<3>Bean初始化
初始化会完成三块:
I、初始化前置执行方法 (配置文件 可以设置,也可以使用)
II、初始化方法
III、初始化后置执行方法
<4>使用Bean(这一步可以算在周期内,比较实例Bean对象就是需要用的)
<5>销毁Bean
如何销毁:Spring会调用Bean的销毁方法,例如实现DisposableBean接口的destroy()方法或者使用@Bean注解的destroyMethod属性指定的自定义销毁方法
刚刚接触会有点抵触;
这里举一个事例来解释以上操作:人的一生(只是举例解释,不要自我带入)
<1>出生(实例化,从无到有)
<2>出生后上户口,名字,性别,家庭关系(设置属性)
<3>开始一系列成长学习(各种初始化)
<4>成人以后,开始正常生活,各种繁杂工作和事务(使用Bean)
<5>退休后(Bean销毁)
3.3、Bean生命周期演示
BeanComponent类的代码:
public class BeanComponent implements BeanNameAware, InitializingBean, BeanPostProcessor {
//BeanNameAware 接口的中的方法重写 实例通知
@Override
public void setBeanName(String s) {
System.out.println("执行通知 BeanName "+s);
}
// xml配置文件的初始化执行方法
public void myInit(){
System.out.println("xml 初识化方法");
}
//注解执行初始化方法方法
@PostConstruct
public void doPostConstruct(){
System.out.println("注解的初识化方法");
}
//使用bean方法
public void sayHi(){
System.out.println("执行 sayHI()方法");
}
//Bean销毁方法 对应的一个注解 销毁
@PreDestroy
public void doPreDestroy(){
System.out.println("doPreDestroy ...");
}
//前置初始化执行方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("前置执行方法");
}
//后置初始化执行方法
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("后置执行方法");
return bean;
}
}
注:这里加不加类注解都可以因为我们同时使用bean标签和content 标签注册Bean对象(如果对以上接口比较好奇的话,可以百度以下,作为了解,主要是为了Bean的生命周期)
运行结果:
这里不难发现初始化方法执行顺序:(这里了解一下就行)
@PostConstruct > init-method
3.4、图解Bean生命周期
注:以上接口或者方式不唯一,也不一定就只有上面这几种。