当一个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作用域的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
“属性)。
request
、session
以及global session
仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架)。
要使用request
、session
和 global 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>
针对每次HTTP请求,Spring容器会根据loginAction
bean定义创建一个全新的LoginAction
bean实例,且该loginAction
bean实例仅在当前HTTP request内有效,因此可以根据需要放心的更改所建实例的内部状态,而其他请求中根据loginAction
bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。当处理请求结束,request作用域的bean实例将被销毁。
<bean id="loginAction" class="com.foo.LoginAction" scope="request"/>
针对某个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
作用域类似于标准的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"/>