Bean 作用域
在定义 <bean> 标签时可以定义 bean 的 scope。
Bean scope 的类型
Spring Framework 中提供了如下的 scope:
- singleton,默认,在一个容器中每一个 bean 都是单例
- prototype,一个 bean 定义有多个 object instances,每一次调用 getBean 都创建一个实例
- request,每一个 HTTP 请求都会生成一个实例,Bean 仅在当前 HTTP 请求内有效,Only valid in the context of a web-aware Spring ApplicationContext.
- session,每一个 HTTP 会话都会生成一个实例,Bean 仅在当前 HTTP session 请求内有效 Only valid in the context of a web-aware Spring ApplicationContext.
- global-session,This scopes a bean definition to a global HTTP session. Only valid in the context of a web-aware Spring ApplicationContext.
- application,每个 ServletContext 创建一个 Bean 实例
- websocket
比如想要让 Spring 每次都产生一个新的 bean instance,那么需要定义 bean 的 scope 是 prototype。同样如果想要 Spring 每次都返回相同的实例,定义成 singleton。
<!-- A bean definition with singleton scope -->
<bean id = "..." class = "..." scope = "singleton">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- A bean definition with prototype scope -->
<bean id = "..." class = "..." scope = "prototype">
<!-- collaborators and configuration for this bean go here -->
</bean>
The singleton scope
只有一个共享的实例被管理,所有对这个 id bean 的请求都会指定到唯一一个被 Spring 容器管理的 bean。
Spring 概念中的单例 Bean 和定义在 Gang of Four 一书中定义的单例是不一样的。
- GoF 中定义的单例作用域值得是,对于特定 class ,在一个 ClassLoader 中有且仅有一个实例。(one and only one instance of a particular class in created per ClassLoader)
- 而 Spring 概念中的单例作用域最好的描述是一个容器一个 Bean (per container and per bean)。
The prototype scope
定义
<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/>
和其他作用域不相同的是,Spring 不会完整的管理 prototype bean 的生命周期:容器初始化,配置,然后聚合 (assemble) 一个 prototype object,然后将它交给客户端,不会记录该实例。
因此,尽管 initialization 生命周期的回调方法会被调用,在 prototype 对象中,destruction 的回调并不会被调用。客户端必须自己清理 prototype 对象的资源。