Spring中bean的scope有六种:singleton,prototype,request,session,global session,application。此外,用户还可以自定义scope。还有一种scope是thread类型的,但是默认没有启用。
singleton是默认的scope。全局范围内只有一个bean被托管,所有对它的请求或者引用都是指向的这个Spring容器内的唯一实例。
换句话说,当你定义了一个singleton的bean以后,Spring 的 IoC容器会创建且仅创建一个对象的实例。这个实例会保存在singleton bean的缓存中,所有的请求和引用都返回这个缓存中的对象。
Spring的singletonbean概念不同于24种设计模式(Gang of Four, GoF)中的单例模式,单例模式在编码中定义了对于每一个 ClassLoader 都只会产生唯一实例,而Spring的singleton bean是在每一个Spring容器中产生唯一bean。
要使用xml定义bean,可以这样
<bean id="accountService" class="com.foo.DefaultAccountService"/> 或 <bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/>
明确指明singleton的scope有些多余,不过可以接受。
prototype的scope是另一种常用的bean,是和singleton相对的。对于每一次请求该bean,spring都会创建一个新的实例。prototype的是有状态bean,singleton是无状态bean。
使用xml创建方式如下
<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/>
不同于其他scope,Spring不会管理prototype的bean。尽管所有scope的bean初始化回调都会被调用,但是对于prototype的bean,Spring不会调用其销毁回调。必要的时候,用户需要同代码来销毁其。
request和session已经global session都是web模式下才能使用的。如果使用ClassPathXmlApplicationContext初始化容器,会报错IllegalStateException。
要是有这些scope,需要做一些额外的配置(上述两种不需要)。在Spring MVC中,如果通过DispatcherServlet 或 DispatcherPortlet 过滤请求就不需要更多修改了,因为它们包含了相关的状态。
如果没有使用Spring 的MVC,比如使用了Struts,对于Servlet 2.5需要注册org.springframework.web.context.request.RequestContextListener。对于Servlet 3.0以上,可以通过WebApplicationInitializer代码配置这个监听器。在web.xml中配置方式如下:
<web-app> ... <listener> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class> </listener> ... </web-app>
如果容器不支持这种方式,可以使用过滤器RequestContextFilter:
<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>
application的scope和singleton的很像,不过有两点区别:application的是对于每个ServletContext产生一个实例而非每个Spring容器;另外它是ServletContext可见的。