Bean作用域和生命周期
一,Bean作用域
Bean作用域指的是在Spring框架中,定义了Bean实例的创建和销毁方式,以及可以访问该实例的范围,并决定了每次通过容器获取Bean时返回的是同一个实例还是不同的实例。
1.1,Bean作用域介绍
Spring 容器在初始化一个 Bean的实例时,同时会指定该实例的作用域,Bean作用域有以下6种,分别为:
1,Singleton:单例作用域【Spring 默认作用域】
- 在整个应用程序中只存在一个Bean实例。
- Spring容器会在第一次请求该Bean时创建实例。
- 并在后续每次请求该Bean时,容器都返回并重用同一个实例。
2,Prototype:原型作用域【也称多例作用域】
- 每次请求该Bean时,容器都创建一个新的实例。
- 每个实例都有独立的状态,不共享状态。
- 适用于需要每次请求都获得一个新的对象的场景。
3,Request:请求作用域【限定于Spring MVC 使用】
-
每个HTTP请求都会创建一个新的Bean实例,该实例仅在当前请求范围内有效。
-
在同一个请求中,多个组件可以共享同一个Request作用域的Bean。
-
适用于每个请求需要独立实例的Web应用程序的场景。
4,Session:会话作用域【限定于Spring MVC 使用】
- 每个HTTP会话(Session)都会创建一个新的Bean实例,该实例会在整个会话期间保持有效。
- 不同用户的不同会话期间,会有独立的Session作用域Bean。
- 适用于需要在每个用户会话中使用独立的Bean实例的Web应用程序。
5,Application:全局作用域【限定于Spring MVC 使用】
- 在整个Web应用程序的生命周期中,只有一个Bean实例。
- 每次请求该Bean时,都返回同一个实例。
- 适用于需要在整个Web应用程序中共享数据或状态的情况。
6,Websocket:HTTP WebSocket 作用域【限定于Spring WebSocket 使用】
- 在⼀个HTTP WebSocket的⽣命周期中,定义⼀个Bean实例。
- 第⼀次初始化Bean后,直到WebSocket结束都是同⼀个Bean。
1.2,Bean作用域的设置
使用@Scope标签就可以用来声明Bean的作用域,@Scope 标签既可以修饰方法也可以修饰类。
@Scope 有两种设置方式:
1,直接设置值:
@Scope("prototype")
2,使用枚举设置:
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
二,Bean生命周期
2.1,Bean生命周期流程
Bean的生命周期指的是Bean对象由诞生到销毁的过程,可大致分为以下5步:
1,Bean实例化:Spring 容器根据配置或注解创建Bean的实例,为其分配内存空间。
2,属性设置:Spring容器会通过依赖注入【DI】或自动装配【Autowiring】的方式将配置的属性值设置给Bean的对应属性
3,初始化:
- 各种通知:Spring容器会检测Bean是否实现了特定的Aware接口,然后通过这些接口回调方法通知Bean获取相关的信息。
- 例如
BeanNameAware
、BeanFactoryAware
、ApplicationContextAware
等接口以获得对应对象的引用。
- 例如
- 初始化前置方法:检测所有注册的
BeanPostProcessor
接口的实现类,并依次调用它们的前置处理方法。- 可以通过实现
postProcessBeforeInitialization()
方法,对Bean进行一些额外的处理或修改。
- 可以通过实现
- 初始化方法:调用Bean的实际初始化方法,可简单地看作是Bean的构造完成后,进行一些额外的初始化工作的方法。
- 可以通过XML配置文件的
init-method
属性、使用@PostConstruct
注解或实现InitializingBean
接口的afterPropertiesSet()
方法来指定初始化方法。
- 可以通过XML配置文件的
- 初始化后置方法:会继续调用所有注册的
BeanPostProcessor
接口的实现类,并依次调用它们的后置处理方法。- 可以通过实现
postProcessAfterInitialization()
方法,对Bean进行任何需要的进一步处理
- 可以通过实现
4,使用Bean:Bean就可以在应用程序中根据业务逻辑调用和操作Bean。
5,销毁Bean:
- 销毁前置方法:在应用程序关闭或手动销毁Bean时,Spring容器会调用Bean的销毁前置方法。
- 可以通过配置XML文件中的
destroy-method
属性,或使用@PreDestroy
注解来指定特定的方法。
- 可以通过配置XML文件中的
- 销毁方法:在销毁前置方法之后,Spring容器将调用Bean的销毁方法,这可以将其简单地看作清理资源、释放连接等操作的方法。
- 通过实现
DisposableBean
接口的方法,以达到执行清理逻辑的功能。
- 通过实现
2.2,Bean生命周期流程图
Bean生命周期基本流程图:
2.3,Bean生命周期流程实现
Bean生命周期流程代码实现:
package com.java.component;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class BeanComponent implements BeanNameAware, BeanPostProcessor {
@Override
public void setBeanName(String s) {
System.out.println("执行通知 BeanName 【" + s + "】");
}
@Override
public Object postProcessBeforeInitialization(Object bean,String beanName){
System.out.println("do postProcessBeforeInitialization 初始化前置方法!【" + beanName + "】");
return bean;
}
private void myInit(){
System.out.println("do xml方式初始化");
}
@PostConstruct
private void doPostConstruct(){
System.out.println("do 注解方式初始化");
}
@Override
public Object postProcessAfterInitialization(Object bean,String beanName){
System.out.println("do postProcessAfterInitialization 初始化后置方法!【" + beanName + "】");
return bean;
}
public void sayHi(){
System.out.println("do sayHi()");
}
@PreDestroy
public void doPreDestroy(){
System.out.println("do 注解方式销毁1");
}
public void close(){
System.out.println("do xml方法销毁");
}
}
代码实现配置文件:
Bean生命周期流程代码运行结果:
思考:为什么在xml里面配置了init-method和destory-method,打印结果时,init方法就会运行,而destory方法不手动调用就不会运行?
解答:是因为配置文件里设置Bean作用域为多例作用域,在多例作用域里,如果未手动调用destory方法,就不会对Bean进行销毁,
而设置Bean作用域为单例作用域,销毁Spring容器时,会先自动调用destory方法进行对Bean的销毁,然后再对Spring容器进行销毁。
理由:当使用多例作用域时,Spring 容器并不会自动调用 destroy 方法来销毁 Bean 实例。多例作用域的 Bean 生命周期由使用者负责管理,如果需要销毁一个多例 Bean 实例,需要显式地调用 destroy 方法或者手动释放相关资源。而当使用单例作用域时,在销毁Spring 容器时,Spring 会自动调用单例 Bean 的 destroy 方法来进行销毁操作,以确保在应用程序关闭时正确地释放资源。
需要注意的是,destroy 方法只针对单个 Bean 进行销毁操作。对于多例模式,如果存在多个实例,需要手动进行销毁操作,先销毁所有的 Bean 实例,然后再销毁 Spring 容器。
总结
1,Bean作用域介绍?
Bean作用域指的是在Spring框架中,定义了Bean实例的创建和销毁方式,以及可以访问该实例的范围,并决定了每次通过容器获取Bean时返回的是同一个实例还是不同的实例。Bean作用域有以下6种,分别为:
- Singleton:单例作用域【Spring 默认作用域】
- Prototype:原型作用域【也称多例作用域】
- Request:请求作用域【限定于Spring MVC 使用】
- Session:会话作用域【限定于Spring MVC 使用】
- Application:全局作用域【限定于Spring MVC 使用】
- Websocket:HTTP WebSocket 作用域【限定于Spring WebSocket 使用】
2,Bean作用域的设置?
使用@Scope标签就可以用来声明Bean的作用域,@Scope 标签既可以修饰方法也可以修饰类。
@Scope 有两种设置方式,分别为直接设置值和使用枚举设置。
1,直接设置值:
@Scope("prototype")
2,使用枚举设置:
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
3,Bean生命周期流程?
Bean的生命周期指的是Bean对象由诞生到销毁的过程,可大致分为以下5步:
1,Bean实例化:Spring 容器根据配置或注解创建Bean的实例,为其分配内存空间。
2,属性设置:Spring容器会通过依赖注入【DI】或自动装配【Autowiring】的方式将配置的属性值设置给Bean的对应属性
3,初始化:
- 各种通知:Spring容器会检测Bean是否实现了特定的Aware接口,然后通过这些接口回调方法通知Bean获取相关的信息。
- 初始化前置方法:检测所有注册的
BeanPostProcessor
接口的实现类,并依次调用它们的前置处理方法。 - 初始化方法:调用Bean的实际初始化方法,可简单地看作是Bean的构造完成后,进行一些额外的初始化工作的方法。
- 初始化后置方法:会继续调用所有注册的
BeanPostProcessor
接口的实现类,并依次调用它们的后置处理方法。
4,使用Bean:Bean就可以在应用程序中根据业务逻辑调用和操作Bean。
5,销毁Bean:Spring容器将调用Bean的销毁方法,这可以将其简单地看作清理资源、释放连接等操作的方法。
Bean生命周期基本流程图:
结语
这就是本期博客的全部内容啦!如果有什么其他的问题无法自己解决,可以在评论区留言哦!
最后,如果你觉得这篇文章写的还不错的话或者有所收获的话,麻烦小伙伴们动动你们的小手,给个三连呗(点赞👍,评论✍,收藏📖),多多支持一下!各位的支持是我最大的动力,后期不断更新优质的内容来帮助大家,一起进步。那我们下期见!