不,对于HttpServletRequest,这不会是一个问题,对于其他请求范围的bean也不应该。基本上,Spring 将生成一个代理HttpServletRequest,它包装了某种知道如何检索实际实例的ObjectFactory(RequestObjectFactory for HttpServletRequest)(YMMV)。当您使用此代理的任何方法时,它们将委托给该实例。
更重要的是,这是延迟完成的,所以它不会在初始化时失败。但是,如果您在没有可用请求的情况下尝试使用 bean(或者如果您尚未注册 RequestScope),它将失败。
以下是针对cmets的回应和一般性的澄清。
关于@Scope 的proxy-mode 属性或等效的XML,默认是 ScopedProxyMode.NO。但是,正如 javadoc 所述
这种代理模式在与非单例一起使用时通常没有用处
范围内的实例,应该有利于使用 INTERFACES 或
如果将其用作依赖项,则改为使用 TARGET_CLASS 代理模式。
对于请求范围的 bean,此 proxy-mode 值将不起作用。您需要使用 INTERFACES 或 TARGET_CLASS,具体取决于您想要的配置。
将scope 设置为request(使用常量WebApplicationContext.SCOPE_REQUEST),Spring 将使用RequestScope 其中
依赖于线程绑定的RequestAttributes 实例,可以是
通过RequestContextListener、RequestContextFilter 或导出
DispatcherServlet.
让我们举这个简单的例子
@Component
@Scope(proxyMode = ScopedProxyMode.INTERFACES, value = WebApplicationContext.SCOPE_REQUEST)
public class RequestScopedBean {
public void method() {}
}
...
@Autowired
private RequestScopedBean bean;
Spring 将生成 两个 bean 定义:一个用于注入的 bean,一个单例,一个用于在每个请求上生成的请求范围 bean。
根据这些 bean 定义,Spring 将使用目标类的类型将单例初始化为代理。在此示例中,即为RequestScopedBean。代理将包含它需要的状态来生成或在需要时返回实际的 bean,即。在代理上调用方法时。例如,当
bean.method();
被调用。
这个状态基本上是对底层BeanFactory 的引用和请求范围的bean 定义的名称。它将使用这两个生成一个新 bean,然后在该实例上调用 method()。
documentation 状态
Spring IoC 容器不仅管理您的实例化
对象(bean),还有协作者(或
依赖项)。 如果你想注入(例如)一个 HTTP 请求
作用域 bean 到另一个 bean,你必须在适当的位置注入一个 AOP 代理
范围 bean。 也就是说,您需要注入一个代理对象
公开与作用域对象相同的公共接口,但可以
还从相关范围检索真实的目标对象(对于
例如,一个 HTTP 请求)并将方法调用委托给真实的
对象。
如果正确实施,所有急切加载的请求范围 bean 都将成为代理。类似地,未急切加载的请求范围 bean 要么是代理本身,要么是通过代理加载。如果没有HttpSerlvetRequest 绑定到当前线程,这将失败。基本上,对于请求范围的 bean,在 bean 依赖链的某个地方需要一个代理。