ITEEDU

Spring中Bean的作用域

Singleton作用域

当一个bean的作用域为singleton, 那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。

Singleton作用域是Spring中的缺省作用域。要在XML中将bean定义成singleton,可以这样配置:

<bean id="accountService" class="com.foo.DefaultAccountService"/>

<bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/>

<bean id="accountService" class="com.foo.DefaultAccountService" singleton="true"/>

 Prototype作用域

Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。根据经验,对所有有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。

要在XML中将bean定义成prototype,可以这样配置:

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

<bean id="accountService" class="com.foo.DefaultAccountService" singleton="false"/>

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

如果你在bean定义文件中引用'spring-beans.dtd' DTD,要显式说明bean的生命周期作用域你必须使用”singleton“属性。如果引用的是'spring-beans-2.0.dtd' DTD或者是Spring 2.0 XSD schema,那么需要使用”scope“属性(因为”singleton“属性被删除了,新的DTD和XSD文件使用”scope“属性)。

其他作用域

requestsession以及global session仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架)。

初始化web配置

要使用requestsessionglobal session作用域的bean(即具有web作用域的bean),在开始设置bean定义之前,还要做少量的初始配置。

使用的是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>

用的是早期版本的web容器(Servlet 2.4以前),那么你要使用一个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>

 Request作用域

针对每次HTTP请求,Spring容器会根据loginAction bean定义创建一个全新的LoginAction bean实例,且该loginAction bean实例仅在当前HTTP request内有效,因此可以根据需要放心的更改所建实例的内部状态,而其他请求中根据loginAction bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。当处理请求结束,request作用域的bean实例将被销毁。

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

 Session作用域

针对某个HTTP Session,Spring容器会根据userPreferences bean定义创建一个全新的userPreferences bean实例,且该userPreferences bean仅在当前HTTP Session内有效。与request作用域一样,你可以根据需要放心的更改所创建实例的内部状态,而别的HTTP Session中根据userPreferences创建的实例,将不会看到这些特定于某个HTTP Session的状态变化。当HTTP Session最终被废弃的时候,在该HTTP Session作用域内的bean也会被废弃掉。

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

 global session作用域

global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个portlet web应用的各种不同的portlet所共享。在global session作用域中定义的bean被限定于全局portlet Session的生命周期范围内。

请注意,假如你在编写一个标准的基于Servlet的web应用,并且定义了一个或多个具有global session作用域的bean,系统会使用标准的HTTP Session作用域,并且不会引起任何错误。

<bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/>