Bean 作用域

在Bean定义时,会定义一个作用域,表示在容器中获取的Bean的类型。在配置属性的时候可以设置Bean的作用域,Spring支持6中作用域。

下表描述了支持的范围:

范围 描述
singleton (默认)将bean作用域限定为每个 Spring IoC 容器的单个对象实例。
prototype 将bean作用域限定为任意数量的对象实例。
request 将bean作用域限定为单个 HTTP 请求的生命周期。也就是说,每个 HTTP 请求都有自己的 bean 实例。
session 将bean作用域限定为 HTTP 的生命周期Session
application 将bean作用域限定为ServletContext
websocket 将bean作用域限定为WebSocket

从 Spring 3.0 开始,线程作用域可用,但默认情况下未注册。

详细说明

单例

标志容器中只会存在一个实例,每次获取的都是同一个Bean,包括注入到其他的Bean中

下图说明了这种情况

可以看到,所有的请求都使用相同的实例,但是这个单例不同于Gof定义的单例模式,硬性的在编码中指定只会存在一个实例,这个单例指的是如果把某个类设置为单例,表示在使用过程中,容器只会创建一个Bean。

1
2
3
<bean id="accountService" class="com.something.DefaultAccountService"/>
<!-- the following is equivalent, though redundant (singleton scope is the default) -->
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>

原型

原型作用域表示在一个容器中每一次注入(inject)和getBean()的时候都会返回一个新的实例,一般来说,在有状态的bean中使用原型,在无状态的bean中使用单例

通常把dao层对象设置成单例,因为dao对象一般不会保持一个会话状态

1
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>

单例bean依赖原型bean

如果一个设置为singleton的bean依赖prototype的bean,则只会在获取原型bean的时候注入一次,之后获取就不会重新注入,因为原型bean只会发生一次初始化

请求

当一个bean被定义为requestui

1
<bean id="loginAction" class="com.something.LoginAction" scope="request"/>

作用域就会被限定在单个http请求,在请求结束后就会被抛弃

注解方式

1
2
3
4
5
@RequestScope
@Component
public class LoginAction {
// ...
}

会话

类似于请求,作用域限定在单个http session,当会话过期,bean也会被抛弃

xml配置

1
<bean id="userPreferences" class="com.something.UserPreferences" scope="session"/>

注解配置

1
2
3
4
5
@SessionScope
@Component
public class UserPreferences {
// ...
}

应用

配置如下

1
<bean id="appPreferences" class="com.something.AppPreferences" scope="application"/>

Spring 容器AppPreferences通过appPreferences对整个 Web 应用程序使用一次 bean 定义来创建bean 的新实例。也就是说, appPreferencesbean 的作用域在ServletContext级别并存储为常规 ServletContext属性。作为一个单例在容器中作为一个属性

1
2
3
4
5
@ApplicationScope
@Component
public class AppPreferences {
// ...
}