Spring Scope Bean是Spring框架中用于管理Bean的作用域的机制,它定义了Bean的生命周期和实例化策略 。通过合理地选择Bean的作用域,可以优化应用的性能和资源利用率 。环境:Spring5.3.23
一. 简介Spring Scope Bean是Spring用于管理Bean的作用域的一种机制 。它定义了容器中Bean的生命周期和实例化策略,即如何创建Bean实例 。
在Spring中 , Bean的作用域包括单例(singleton)、原型(prototype)、请求(request)、会话(session)等 。每个作用域都有其特定的使用场景和行为:
- 单例(singleton):这是Spring默认的作用域,表示在整个Spring容器中,只有一个Bean实例存在 。无论你从哪个地方获取这个Bean , 都将返回同一个实例 。
- 原型(prototype):每次从容器中请求Bean时,都会创建一个新的Bean实例 。
- 请求(request):在一个HTTP请求的范围内,Bean是单例的 。这种作用域适用于与单个请求关联的Bean 。
- 会话(session):在一个HTTP会话的范围内,Bean是单例的 。这种作用域适用于与单个用户会话关联的Bean 。
通过合理地选择Bean的作用域,可以优化应用的性能和资源利用率 。例如 , 对于需要频繁创建和销毁实例的Bean,使用原型作用域会更高效;而对于需要在多个请求或会话之间共享状态的Bean , 则可以选择单例或会话作用域 。附官方图:
文章插图
图片
接下来将分别介绍每一种作用域bean 。
二. 作用域应用基础类
static class Person {@Overridepublic String toString() {return super.toString() + " - " + this.hashCode() + "" ;}}
2.1 单例(singleton)默认使用@Bean,@Service,@Controller注解标注的注解都是单例的 。也可以同@Scope注解指定作用域为单例@Bean// 不指定@Scope默认就是单例@Scope(value = https://www.isolves.com/it/cxkf/jiagou/2024-01-05/"singleton")public Person person() {return new Person() ;}
测试try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {context.registerBean(Config.class) ;context.refresh() ;System.out.println(context.getBean(Person.class)) ;System.out.println(context.getBean(Person.class)) ;}
控制台输出com.pack.mAIn.scope.ScopeMain5$Person@5e0e82ae - 1578009262com.pack.main.scope.ScopeMain5$Person@5e0e82ae - 1578009262
每次获取的都是同一个实例 。原理
public abstract class AbstractBeanFactory {protected <T> T doGetBean(...) {// ...// 判断是否是单例if (mbd.isSingleton()) {// 先从单例池中查找是否已经存在 , 不存在则调用createBean创建,// 然后存入单例池中sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}});}// ...}}
2.2 原型(prototype)每次从容器中请求Bean时 , 都会创建一个新的Bean实例 。@Bean@Scope(value = https://www.isolves.com/it/cxkf/jiagou/2024-01-05/"prototype")public Person person() {return new Person() ;}
控制台输出com.pack.main.scope.ScopeMain5$Person@fa4c865 - 262457445com.pack.main.scope.ScopeMain5$Person@3bd82cf5 - 1004023029
每次获取都是不同的对象 。原理
public abstract class AbstractBeanFactory {protected <T> T doGetBean(...) {// ...// 判断是否是单例if (mbd.isSingleton()) {// ...}// 判断是否是原型else if (mbd.isPrototype()) {Object prototypeInstance = null;try {// 不存在什么缓存池,直接创建bean实例返回prototypeInstance = createBean(beanName, mbd, args);}}// ...}}
这里考虑一个问题,如何在单例bean中正确的注入原型bean?2.3 请求(request)接下来都是与web环境相关了,所以这里演示的示例会以SpringBoot3.0.5环境演示 。
基础类
@Component@Scope(value = https://www.isolves.com/it/cxkf/jiagou/2024-01-05/"request")public class Person {}
测试类@RestController@RequestMapping("/scopes")public class ScopeController {@Resourceprivate Person person ;@Resourceprivate PersonService ps ;@GetMapping("/request")public Person request() {System.out.println("ScopeController: " + person) ;ps.query() ;return person ;}}
Service@Servicepublic class PersonService {@Resourceprivate Person person ;public void query() {System.out.println("PersonService: " + person) ;}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Spring Boot Starter的原理
- Spring 七种事务传播性介绍
- 摩飞便携榨汁杯体验
- 简易版的SpringBoot是如何实现的!!!
- 钓鱼饵料指南:各种饵料特点与使用技巧
- 各种钢材的尺寸与重量大全
- 网络用语有那些各指什么意思 各种网络用词的意思
- Spring非常实用的技巧,你确定知道?
- 当年一瓶雪花膏闯天下,现在护肤用的各种水都是智商税吗?
- Java Lambda 表达式各种用法,你都会了吗