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 对象的资源。

reference