java八股文面试[Spring]——Spring中支持几种作用域

Spring容器中的bean可以分为5个范围

  1. prototype:为每一个bean请求提供一个实例。

  2. singleton:默认,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。

  3. request:为每一个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。

  4. session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。

  5. global-session:全局作用域,global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。

<!-- 默认的作用域:singleton -->
<bean id="p1" class="com.abc.Person" /> 
<!-- 指定的作用域:prototype -->
<bean id="p2" class="com.abc.Person" scope="prototype" />

下面是一个测试类:

public class BeanTest {
  public static void main(String args[]) {
    //加载类路径下的beans.xml文件以初始化Spring容器
    ApplicationContext context = new ClassPathXmlApplicationContext();
    //分两次分别取同一个Bean,比较二者是否是同一个对象
    System.out.println(context.getBean("p1") == context.getBean("p1"));
    System.out.println(context.getBean("p2") == context.getBean("p2"));
  }
}

执行结果分别是:true和false

从结果可以看出,正如上文所述:对于singleton作用域的Bean,每次请求该id的Bean,都将返回同一个实例,而prototype作用域的Bean, 每次请求都将产生全新的实例。
 

自定义作用域

如果BeanDefinition既不是singleton,也不是prototype,那么就会执行自定义作用域的创建规则:

  1. 获取BeanDefinitionscope属性值。
  2. BeanFactory的作用域缓存scopes中获取对应的作用域。
  3. 调用scope.get()方法,执行自定义创建规则。
  4. 后处理:Spring AOP功能入口,与singletonprototype相同。
// 1、获取BeanDefinition的scope属性值
String scopeName = mbd.getScope();
// 2、从BeanFactory的作用域缓存scopes中获取对应的作用域
Scope scope = this.scopes.get(scopeName);
try {
   // 3、执行自定义创建规则
   Object scopedInstance = scope.get(beanName, () -> {
      beforePrototypeCreation(beanName);
      try {
         return createBean(beanName, mbd, args);
      }
      finally {
         afterPrototypeCreation(beanName);
      }
   });
   // 4、后处理
   beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
   throw new ScopeNotActiveException(beanName, scopeName, ex);
}

从以上源码中我们可以得出自定义作用域的三个步骤:

  1. 创建作用域实现类:实现org.springframework.beans.factory.config.Scope接口,实现其get()方法。

mermaid classDiagram class Scope Scope : +get(String name, ObjectFactory<?> objectFactory)

  1. 将作用域实现类注册到BeanFactoryscopes缓存中:key为作用域名,value为自定义作用域对象(org.springframework.beans.factory.config.ConfigurableBeanFactory#registerScope)。
  2. 配置Bean时,指定对应的作用域名。

内置作用域和自定义作用域的区别?

内置作用域的作用域名和bean创建规则已经写死到Spring IoC容器中。

自定义作用域通过自定义的作用域名BeanFactoryscopes缓存中找到自定义作用域实现类,根据其中实现的get()方法创建bean。同时,自定义作用域的bean对象存放于自定义的缓存中。

知识来源:马士兵教育

Spring支持如下5种作用域_spring的五种作用域_杨航JAVA的博客-CSDN博客

Spring bean支持的作用域有? - 知乎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小田田_XOW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值