SpringBean作用域

开课吧开课吧锤锤2021-08-06 14:07

在配置文件中,除了可以定义Bean的属性值和相互之间的依赖关系,还可以声明Bean的作用域。例如,如果每次获取Bean时,都需要一个Bean实例,那么应该将Bean的scope属性定义为prototype,如果Spring需要每次都返回一个相同的Bean实例,则应将Bean的scope属性定义为singleton。  

SpringBean作用域

作用域的种类  

Spring容器在初始化一个Bean实例时,同时会指定该实例的作用域。Spring5支持以下6种作用域。  

1)singleton  

默认值,单例模式,表示在Spring容器中只有一个Bean实例,Bean以单例的方式存在。  

2)prototype  

原型模式,表示每次通过Spring容器获取Bean时,容器都会创建一个Bean实例。  

3)request  

每次HTTP请求,容器都会创建一个Bean实例。该作用域只在当前HTTPRequest内有效。  

4)session  

同一个HTTPSession共享一个Bean实例,不同的Session使用不同的Bean实例。该作用域仅在当前HTTPSession内有效。  

5)application  

同一个Web应用共享一个Bean实例,该作用域在当前ServletContext内有效。  

类似于singleton,不同的是,singleton表示每个IoC容器中仅有一个Bean实例,而同一个Web应用中可能会有多个IoC容器,但一个Web应用只会有一个ServletContext,也可以说application才是Web应用中货真价实的单例模式。  

6)websocket  

websocket的作用域是WebSocket,即在整个WebSocket中有效。  

注意:Spring5版本之前还支持globalSession,该值表示在一个全局的HTTPSession中,容器会返回该Bean的同一个实例。一般用于Portlet应用环境。Spring5.2.0版本中已经将该值移除了。  

request、session、application、websocket和globalSession作用域只能在Web环境下使用,如果使用ClassPathXmlApplicationContext加载这些作用域中的任意一个的Bean,就会抛出以下异常。  

java.lang.IllegalStateException: No Scope registered for scope name 'xxx'

下面我们详细讲解常用的两个作用域:singleton和prototype。  

singleton  

singleton是Spring容器默认的作用域。当Bean的作用域为singleton时,Spring容器中只会存在一个共享的Bean实例。该Bean实例将存储在高速缓存中,并且所有对Bean的请求,只要id与该Bean定义相匹配,都会返回该缓存对象。  

通常情况下,这种单例模式对于无会话状态的Bean(如DAO层、Service层)来说,是最理想的选择。  

在Spring配置文件中,可以使用<bean>元素的scope属性,将Bean的作用域定义成singleton,其配置方式如下所示:  

<bean id="..." class="..." scope="singleton"/>

例1  

下面使用EclipseIDE演示如何将Bean的作用域指定为singleton,步骤如下:  

1、创建SpringDemo项目,并在src目录下创建net.biancheng包。  

2、添加相应的jar包,可以参考《第一个Spring程序》一节。  

3、在net.biancheng包下创建HelloWorld和MainApp类。  

4、在src目录下创建Spring配置文件Beans.xml。  

运行SpringDemo项目。  

HelloWorld类代码如下。  

package net.biancheng;
public class HelloWorld {
    private String message;
    public void setMessage(String message) {
        this.message = message;
    }
    public void getMessage() {
        System.out.println("message : " + message);
    }
}

MainApp类如下。  

package net.biancheng;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        HelloWorld objA = (HelloWorld) context.getBean("helloWorld");
        objA.setMessage("对象A");
        objA.getMessage();
        HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
        objB.getMessage();
    }
}

Beans.xml文件内容如下。  

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean id="helloWorld" class="net.biancheng.HelloWorld" scope="singleton"/>
      
</beans>

运行结果如下。 

message : 对象A
message : 对象A

从运行结果可以看出,两次输出内容相同,这说明Spring容器只创建了一个HelloWorld类的实例。由于Spring容器默认作用域是singleton,所以如果省略scope属性,其输出结果也会是一个实例。  

prototype  

对于prototype作用域的Bean,Spring容器会在每次请求该Bean时都创建一个新的Bean实例。prototype作用域适用于需要保持会话状态的Bean(如Struts2的Action类)。  

在Spring配置文件中,可以使用<bean>元素的scope属性,将Bean的作用域定义成prototype,其配置方式如下所示:  

<bean id="..." class="..." scope="prototype"/>

例2  

在例1的基础上,修改配置文件Beans.xml,内容如下。  

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean id="helloWorld" class="net.biancheng.HelloWorld" scope="prototype"/>
      
</beans>

运行结果如下。  

message : 对象A
message : null

从运行结果可以看出,两次输出的内容并不相同,这说明在prototype作用域下,Spring容器创建了两个不同的HelloWorld实例。  

以上就是开课吧广场小编为大家整理发布的“SpringBean作用域”一文,更多Java教程相关内容尽在开课吧广场Java教程频道!  

SpringBean作用域

免责声明:本站所提供的内容均来源于网友提供或网络搜集,由本站编辑整理,仅供个人研究、交流学习使用。如涉及版权问题,请联系本站管理员予以更改或删除。
有用
分享