Singleton Beans with Prototype-bean Dependencies
具有原型bean依赖关系的单例bean
When you use singleton-scoped beans with dependencies on prototype beans, be aware that dependencies are resolved at instantiation time. Thus, if you dependency-inject a prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency-injected into the singleton bean. The prototype instance is the sole instance that is ever supplied to the singleton-scoped bean.
当您使用单例范围的bean时,要注意依赖关系是在实例化时解析的。因此,如果依赖关系将原型范围的bean注入到单例范围的bean中,则会实例化一个新的原型bean,然后将依赖关系注入到单例bean中。原型实例是提供给单例范围bean的唯一实例。
However, suppose you want the singleton-scoped bean to acquire a new instance of the prototype-scoped bean repeatedly at runtime. You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container instantiates the singleton bean and resolves and injects its dependencies. If you need a new instance of a prototype bean at runtime more than once, see Method Injection
但是,假设您希望singleton范围的bean在运行时反复获取原型范围bean的新实例。不能将原型范围的bean通过依赖关系注入到singleton bean中,因为这种注入只发生一次,当Spring容器实例化singleton bean并解析和注入它的依赖项时。如果在运行时多次需要原型bean的新实例,请参见方法注入
1.5.4. Request, Session, Application, and WebSocket Scopes
请求、会话、应用程序和WebSocket作用域
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.
只有使用支持web的Spring ApplicationContext
实现(如XmlWebApplicationContext
), request
, session
, application
, and websocket
作用域才可用。如果您将这些作用域与常规springioc容器(例如ClassPathXmlApplicationContext
)一起使用,则会抛出一个illeglStasteException
,该异常抱怨未知的bean作用域。
Initial Web Configuration
初始Web配置
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
.)
为了在request
, session
, application
, and websocket
级别(web范围的bean)支持bean的作用域,在定义bean之前,需要一些小的初始配置。(对于标准作用域:singleton和prototype,不需要这种初始设置。)
How you accomplish this initial setup depends on your particular Servlet environment.
如何完成初始设置取决于特定的Servlet环境。
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 web mvc
中访问作用域bean,实际上是在spring dispatcherservlet
处理的请求中,那么不需要进行特殊设置。DispatcherServlet
已公开所有相关状态。
If you use a Servlet 2.5 web container, with requests processed outside of Spring’s DispatcherServlet
(for example, when using JSF or Struts), you need to register the org.springframework.web.context.request.RequestContextListener
ServletRequestListener
. For Servlet 3.0+, this can be done programmatically by using the WebApplicationInitializer
interface. Alternatively, or for older containers, add the following declaration to your web application’s web.xml
file:
如果您使用Servlet2.5
Web容器,并在Spring的DispatcherServlet
之外处理请求(例如,在使用JSF
或Struts
时),则需要注册org.springframework.web.context.request.RequestContextListener
ServletRequestListener
。对于Servlet3.0+
,这可以通过使用WebApplicationInitializer
接口以编程方式完成。或者,对于较旧的容器,将以下声明添加到web应用程序的web.xml
文件文件:
<web-app>
...
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
...
</web-app>
Alternatively, if there are issues with your listener setup, consider using Spring’s RequestContextFilter
. The filter mapping depends on the surrounding web application configuration, so you have to change it as appropriate. The following listing shows the filter part of a web application:
或者,如果侦听器设置有问题,可以考虑使用Spring的RequestContextFilter
。过滤器映射取决于周围的web应用程序配置,因此您必须根据需要对其进行更改。下表显示了web应用程序的过滤器部分:
<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.
DispatcherServlet
、RequestContextListener
和RequestContextFilter
都执行相同的操作,即将HTTP请求对象
绑定到为该请求提供服务的线程
。这使得请求和会话作用域的bean在调用链的下一级可用。
Request scope
Consider the following XML configuration for a bean definition:
考虑一下bean定义的以下XML配置:
<bean id="loginAction" class="com.something.LoginAction" scope="request"/>
The Spring container creates a new instance of the LoginAction
bean by using the loginAction
bean definition for each and every HTTP request. That is, the loginAction
bean is scoped at the HTTP request level. You can change the internal state of the instance that is created as much as you want, because other instances created from the same loginAction
bean definition do not see these changes in state. They are particular to an individual request. When the request completes processing, the bean that is scoped to the request is discarded.
Spring容器通过为每个HTTP请求使用loginaction
bean定义来创建loginaction
bean的新实例。也就是说,loginaction
bean的作用域是在HTTP请求级别。您可以随意更改创建的实例的内部状态,因为从同一个LoginAction
Bean定义创建的其他实例在状态中看不到这些更改。它们是针对单个请求的。当请求完成处理时,将丢弃该请求范围内的bean。
When using annotation-driven components or Java configuration, the @RequestScope
annotation can be used to assign a component to the request
scope. The following example shows how to do so:
当使用注释驱动的组件或Java配置时,@RequestScope
注释可用于将组件分配给 request
scope。下面的示例演示如何执行此操作:
Java
@RequestScope
@Component
public class LoginAction {
// ...
}
Session Scope
Consider the following XML configuration for a bean definition:
<bean id="userPreferences" class="com.something.UserPreferences" scope="session"/>
The Spring container creates a new instance of the UserPreferences
bean by using the userPreferences
bean definition for the lifetime of a single HTTP Session
. In other words, the userPreferences
bean is effectively scoped at the HTTP Session
level. As with request-scoped beans, you can change the internal state of the instance that is created as much as you want, knowing that other HTTP Session
instances that are also using instances created from the same userPreferences
bean definition do not see these changes in state, because they are particular to an individual HTTP Session
. When the HTTP Session
is eventually discarded, the bean that is scoped to that particular HTTP Session
is also discarded.
Spring容器通过在单个HTTP会话的生命周期内使用UserPreferences
bean定义来创建UserPreferences
bean的新实例。换句话说,userPreferences
bean在HTTP会话级别有效地限定了作用域。与请求作用域bean一样,您可以根据需要更改创建的实例的内部状态,因为其他HTTP会话实例也在使用从同一个userPreferences
bean定义创建的实例,但不会看到这些状态更改,因为它们是特定于单个HTTP会话的。当HTTP会话最终被丢弃时,作用域为该特定HTTP会话的bean也将被丢弃。
When using annotation-driven components or Java configuration, you can use the @SessionScope
annotation to assign a component to the session
scope.
使用注释驱动的组件或Java配置时,可以使用@SessionScope
注释将组件分配给session
scope。
Java
@SessionScope
@Component
public class UserPreferences {
// ...
}
Application Scope
Consider the following XML configuration for a bean definition:
<bean id="appPreferences" class="com.something.AppPreferences" scope="application"/>
The Spring container creates a new instance of the AppPreferences
bean by using the appPreferences
bean definition once for the entire web application. That is, the appPreferences
bean is scoped at the ServletContext
level and stored as a regular ServletContext
attribute. This is somewhat similar to a Spring singleton bean but differs in two important ways: It is a singleton per ServletContext
, not per Spring 'ApplicationContext' (for which there may be several in any given web application), and it is actually exposed and therefore visible as a ServletContext
attribute.
Spring容器通过对整个web应用程序使用一次AppPreferences
bean定义来创建AppPreferences
bean的新实例。也就是说,appPreferences
bean的作用域在ServletContext
级别,并存储为常规的ServletContext
属性。这有点类似于Spring singleton bean,但在两个重要方面有所不同:它是每个ServletContext
的单例,而不是每个Spring的“ApplicationContext
”(在任何给定的web应用程序中可能有多个),它实际上是公开的,因此作为ServletContext
属性可见。
When using annotation-driven components or Java configuration, you can use the @ApplicationScope
annotation to assign a component to the application
scope. The following example shows how to do so:
Java
@ApplicationScope
@Component
public class AppPreferences {
// ...
}