Spring 中 Bean 的 scope 用法解析

本文详细介绍了Spring中Bean的scope,包括singleton、prototype、request、session和global session。singleton保证每个IOC容器只有一个实例,而prototype则为每次请求创建新实例。request和session作用域适用于web应用,分别对应每次HTTP请求和会话。global session在portlet应用中使用。配置scope可通过XML或注解方式完成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

        所谓scope,是指用来声明 IOC 容器中的对象应该处的限定场景或着说是该对象的存货空间;即,在 IOC 容器在对象进入相应的 scope之前,生成并装配这些对象,在该对象不在处于这些 scope 的限定之后,容器通常会销毁这些对象。

1. scope 的分类:

        在 Spring 2.0 之前,scope 有 singleton 和 prototype 两种;

        而在 Spring 2.0 之后,为支持 web 应用的 ApplicatonContext,增加了另外三种:request、session、global session 专用于 web 应用程序上下文的 bean 的类型;因此,默认情况下 Spring 2.0 之后的版本有5种类型的 bean。当然,Spring 2.0 对 bean 的类型的设计进行了重构,并设计出灵活的 bean 类型支持,理论上可以有无数多种类型的 bean,用户可以根据自己的需要增加新的 bean 类型以满足实际应用得需要。

2. singleton (单一实例)

       当 Spring 中某个 bean 的 scope 取值为 singleton 时,表示 Spring IOC 容器中只会存在一个共享的 bean 实例,并且所有对该 bean 的请求只要 id 与该 bean 定义相匹配,则只会返回 bean 的同一个实例。

       也就是说,当把一个bean 定义设置为 singleton 作用域时,Spring IOC 容器只会创建该 bean 定义的唯一实例;这个单一实例会被存储到单例缓存 (singleton cache) 中,并且所有针对该 bean 的后续请求和引用都将返回被缓存的对象实例。

       这里需要注意的是 singleton 作用域和 GOF 设计模式中的单例是完全不同的,单例设计模式表示一个 ClassLoader 中只有一个 class 存在,而这里的 singleton 则表示一个容器对应一个 bean,也就是说当一个 bean 被标识为 singleton 时,Spring 的 IOC 容器中只会存在一个该 bean。

       实例如下:

<bean id="role" class="com.sztxtech.projectsimple.Role" scope="singleton"/>
或者
<bean id="role" class="com.sztxtech.projectsimple.Role" singleton="true"/>

3. prototype 作用域

       prototype 作用域部署的 bean,每一次请求(将其注入到另一个 bean 中,或者以程序的方式调用容器的 getBean()方法)都会产生一个新的 bean 实例,就相当于一个 new 操作;

       对于 prototype 作用域的 bean,有一点非常重要,那就是 Spring 不能对一个 prototype 的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个 prototype 实例后,将它交给客户端,随后就对该 prototype 实例不再过问了。不管哪种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对于 prototype 作用域而言,任何配置好的 bean 的生命周期回调方法都将不会被调用。

       清除 prototype 作用域的对象并释放任何 prototype bean 所持有的昂贵资源都是客户端代码的职责。让 Spring 容器释放请求 singleton 作用域 bean 占用资源的一种可行方式是,通过使用 bean 的后置处理器,该处理器持有要被清除的 bean 的引用。

       实例如下:

<bean id="role" class="com.sztxtech.projectsimple.Role" scope="prototype"/>
或者
<bean id="role" class="com.sztxtech.projectsimple.Role" singleton="false"/>

4. request 作用域

       request 表示该针对每一次 http 请求都会产生一个新的 bean,同时该 bean 仅在当前 http request 内有效;

       request、session、global session 使用的时候首先要在初始化 web 的 web.xml 中做如下配置:

       如果使用的是 Servlet 2.4 及以上的 web 容器,那么仅需要在 web 应用的 xml 声明文件 web.xml 中增加下述 ContextListener 即可:

<web-app>
    ......
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    ......
</web-app>

       但如果是 Servlet 2.4 以前的 web 容器,那么就要使用 javax.servlet.Filter 的实现:

<web-app>
    ......
    <filter>
        <filter-name>requestContextFilter</filter-name>
        <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>requestContextFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    ......
</web-app>

       完成以上配置就可以配置 bean 的作用域了。实例如下:

<bean id="role" class="com.sztxtech.projectsimple.Role" scope="request"/>

5. session 作用域

       session 作用域表示该针对每一次 http 请求都会产生一个新的 bean,同时该 bean 仅在当前 http session 内有效;

       其配置方法和 request 配置实例的前提是一样的,配置好 web 启动文件就可以做如下所示的 bean 配置了:

<bean id="role" class="com.sztxtech.projectsimple.Role" scope="session"/>

6. global session 作用域

       global session 作用域类似于标准的 http session 作用域,不过它仅仅在基于 portlet 的 web 应用中才有意义。Portlet 规范定义了全局 Session 的概念,它被所有构成某个 portlet web 应用的各种不同的 protlet 所共享。在 global session 作用域中定义的 bean 被限定于全局 protlet session 的生命周期范围内。如果在 web 中使用 global session 作用域来标识 bean,那么 web 会自动当成 session 类型来使用。

该作用域的实例配置方法和 request 配置实例的前提是一样的,配置好 web 启动文件就可以做如下所示的 bean 配置了:

<bean id="role" class="com.sztxtech.projectsimple.Role" scope="global session"/>

7. scope 的配置方方式有两种:xml 方式、注解方式

        在以上的示例中使用的都是 xml 配置方式进行配置的;

       对于注解配置,使用前提是,配置 Spring 也是使用注解来配置的;具体示例如下:

@Controller("userAction")
@Scope("prototype")
public class UserAction extends BasicAction<User> {
	private static final long serialVersionUID = 1L;
	
	@Resource(name="userService")
	private UserService userService;
	
	......
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值