1.上下文较为特殊
请大致阅读一下官方的文档
The request, session, application, and websocket scopes are available only if you use a web-aware Spring ApplicationContext implementation (such as XmlWebApplicationContext). If you use these scopes with regular Spring IoC containers, such as the ClassPathXmlApplicationContext, an IllegalStateException that complains about an unknown bean scope is thrown.
对于这四种scope的bean,与singleton和prototype不同的是,它们的上下文有所不同。如果仍然要使用之前了解到的上下文,比如说就会出现异常。
2.必须进行额外的初始化配置
To support the scoping of beans at the request, session, application, and websocket levels (web-scoped beans), some minor initial configuration is required before you define your beans. (This initial setup is not required for the standard scopes: singleton and prototype.)
可以有下列三种配置的方式:
- 使用Spring Web MVC(配置DispatcherServlet)
If you access scoped beans within Spring Web MVC, in effect, within a request that is processed by the Spring DispatcherServlet, no special setup is necessary. DispatcherServlet already exposes all relevant state.
- 配置Spring的ServletRequestListener
如果不是DispatcherServlet接收的请求,则需要进行如下配置
<web-app>
...
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
...
</web-app>
- 配置Spring的RequestContextFilter
如果不是DispatcherServlet接受的请求,除了配置监听器(上面的例子),还可以配置过滤器(或拦截器)
<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>
DispatcherServlet, RequestContextListener, and RequestContextFilter all do exactly the same thing, namely bind the HTTP request object to the Thread that is servicing that request. This makes beans that are request- and session-scoped available further down the call chain.
上面的三种配置方式其实都做了同一件事,就是将请求对象与处理请求的线程绑定。这样,request-scoped和session-scoped可以在调用链的更下层被使用。
Request scope
HTTP请求中的单例
<bean id="loginAction" class="com.something.LoginAction" scope="request"/>
如上面的例子,对于每一个HTTP请求,Spring容器都会创建一个loginAction对象。当这个请求处理完成后,这个bean也就会被销毁。
也就是说,scope为request的bean,它的生存周期与HTTP请求一致,当接收到HTTP请求时,会创建实例(如果有init回调函数,会被调用);当HTTP请求处理完成时,处理请求的线程被销毁,同时scope为request的bean被销毁(如果有destroy回到函数,会被调用)
每一个HTTP请求都会创建各自的scope为request的bean。因此,不用考虑线程安全问题。
使用基于注解的配置定义:
@RequestScope
@Component
public class LoginAction {
// ...
}
Session Scope
HTTP会话中的单例
与上面的requst类似,每当新建立一个HTTP会话,Spring容器就会创建一个bean。
scope为session的bean的声明周期与HTTP会话保持一致。(如果有初始化/销毁的回调方法,在初始化/销毁时都会被调用)
每一个HTTP会话都会创建各自的scope为session的bean。因此,对于不同的会话,不用考虑线程安全问题。
基于XML的定义:
<bean id="userPreferences" class="com.something.UserPreferences" scope="session"/>
基于注解的定义:
@SessionScope
@Component
public class UserPreferences {
// ...
}
Application Scope
ServletContext(web应用)中的单例
在一个web应用中,可能会有多个ApplicationContext,所以,application不等于singleton(singleton是容器中的单例)。
基于XML的定义:
<bean id="appPreferences" class="com.something.AppPreferences" scope="application"/>
基于注解的定义:
@ApplicationScope
@Component
public class AppPreferences {
// ...
}