该篇博客主要阐述关于Bean的作用域(scope)。Spring容器最初提供了两种bean的scope类型:singleton和prototype,在Spring2.0之后又引入了另外三种scope类型:request、session、global session类型。不过这三种类型有所限制:只能在Web应用中使用。也就是说,只有Web应用的ApplicationContext中使用这三个scope才合理,类似如下代码来进行使用

当然很多书是将scope翻译为作用域,但是笔者比较喜欢《Spring揭秘》上对scope的解释“scope用来声明容器中的对象所应该处的限定场景或者说该对象的存活时间,即容器在对象进入其相应的scope之前生成并装配这些对象,在该对象不再处于这些scope的限定之后,容器通常会销毁这些对象”
举个例子:比如我们都处在社会(容器)中,如果把中学教师作为一个类定义,那么当容器初始化这些类之后,中学教师只能局限在中学这样的场景,中学就可以看作中学老师的scope

<bean id="beanname" class="com.linjie.Bean" scope="prototype"/>

该篇博客主要阐述

1、singleton
2、prototype
3、request、session、global session(介绍)

这里写图片描述

一、singleton(单例)

singleton是容器默认的scope,所以写和不写没有区别。scope为singleton的时候,在Spring的IoC容器中只存在一个实例,所有对该对象的引用将共享这个实例。该实例从容器启动,并因为第一次被请求而初始化后,将一直存活到容器退出,也就是说,它与IoC容器“几乎”拥有相同的寿命

singleton的bean具有的特性
  • 对象实例数量:singleton类型的bean定义,在一个容器中只存在一个共享实例,所有对该类型bean的依赖都引用这一单一实例
  • 对象存活时间:singleton类型bean定义,从容器启动,到它第一次被请求而实例化开始,只要容器不销毁或退出,该类型的单一实例就会一直存活

可以看下面的Demo(scope为singleton)


SingletonBean.java

package com.linjie.scope;

public class SingletonBean {
    /*
     * 无参构造方法 
     */
    public SingletonBean() {
        System.out.println("SingletonBean初始化");
    }
}

测试类

package com.linjie.scope;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SingletonTest {
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        SingletonBean singletonbean1 = (SingletonBean) context.getBean("singletonbean");
        SingletonBean singletonbean2 = (SingletonBean) context.getBean("singletonbean");
        System.out.println(singletonbean1);
        System.out.println(singletonbean2);
    }
}

applicationContext.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.xsd">

   <bean id="singletonbean" class="com.linjie.scope.SingletonBean" scope="singleton"/> 

</beans>

结果

这里写图片描述

可以看到显示结果,SingletonBean只初始化了一次,并且打印出来的结果也是一样的


二、prototype(多例)

对于那些请求方不能共享的对象实例,应该将其bean定义的scope设置为prototype。这样,每个请求方可以得到自己对应的一个对象实例。通常,声明为prototype的scope的bean定义类型,都是一些有状态的,比如保存每个顾客信息的对象


可以看下面的Demo(scope为prototype)


PrototypeBean.java

package com.linjie.scope;

public class PrototypeBean {
    public PrototypeBean() {
        System.out.println("Prototype:初始化");
    }
}

测试类

package com.linjie.scope;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class PrototypeTest {
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        PrototypeBean prototypebean1 = (PrototypeBean) context.getBean("prototypebean");
        PrototypeBean prototypebean2 = (PrototypeBean) context.getBean("prototypebean");
        System.out.println(prototypebean1);
        System.out.println(prototypebean2);
    }
}

applicationContext.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.xsd">

        <bean id="prototypebean" class="com.linjie.scope.PrototypeBean" scope="prototype"/>

</beans>

结果

这里写图片描述

可以看到显示结果,PrototypeBean初始化了两次,并且每次打印出来的值也是不一样的


三、request、session、global session(介绍)

这三个scope类型是Spring2.0之后新增加的,它们不像上面两个那么通用,它们只适用于Web应用程序,通常是与XmlWebApplicationContext共同使用(注意:只能使用scope属性才能使用这三种,也就是必须使用XSD文档声明的XML配置文件格式)

1、request

在Spring容器中,即XmlWebApplicationContext会为每个HTTP请求创建一个全新的Request-Processor对象供当前请求使用,当请求结束后,该对象实生命周期就结束。当同时有10个HTTP请求进来的时候,容器会分别针对这10个请求返回10个全新的RequestProcessor对象实例,且它们之间互不干扰。所以严格意义上说request可以看作prototype的一种特例,除了request的场景更加具体

<bean id="requestProcessor" class="......" scope="request"/>
2、session

放到session中的最普遍的信息就是用户登录信息,Spring容器会为每个独立的session创建属于它们自己全新的UserPreferences对象实例。与request相比,除了拥有session scope的bean比request scope的bean可能更长的存活时间,其他没什么差别

<bean id="sessionProcessor" class="......" scope="session"/>
3、global session

global session只有应用在基于portlet的Web应用程序中才有意义,它映射到portlet的global范围的session。如果在普通的基于servlet的Web应用中使了用这个类型的scope,容器会将其作为普通的session类型的scope来对待

什么是portlet

Portlets是一种Web组件-就像servlets-是专为将合成页面里的内容聚集在一起而设计的。通常请求一个portal页面会引发多个portlets被调用。每个portlet都会生成标记段,并与别的portlets生成的标记段组合在一起嵌入到portal页面的标记内。


参考

《Spring揭秘》
《Spring IN ACTION》

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐