[英]Why can I inject request-scoped beans in the absence of a request?
如果我尝试将请求范围的bean注入单例范围的bean,那将失败,因为
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
正如它应该。
(有关代码示例,请参见本文末尾)
我知道三种通过测试变为绿色的方法:
UsingBean
的范围 ([1]不仅仅是解决方案,而且可能会进一步导致问题,但确实会使测试变成绿色。:P)
尽管我确实了解这三个选项背后的想法,但我仍然不明白它们为什么起作用。
我的意思是,即使我在[1]中将范围更改为“ session”,在实例化UsingBean
时我也没有会话或请求。
至于[2]和[3],他们避免在启动时获取实例,但是当他们实际上确实要获取实例时,我仍然没有请求。
但是测试没有失败。 为什么?
代码示例
假设我有一个请求范围的bean
@Repository
@Scope("request")
class RequestScopedBean : ScopedBean{
override fun foo(): String {
return "Hello World"
}
}
用于单例范围的
@Service
class UsingBean{
private val scopedBean:ScopedBean
@Inject
constructor(scopedBean: ScopedBean) {
this.scopedBean = scopedBean
}
fun foo():String{
val foo = scopedBean.foo()
println(foo)
return foo
}
}
我们还为此创建一个小测试:
@RunWith(SpringJUnit4ClassRunner::class)
@SpringBootTest
@WebAppConfiguration
class RequestScopedBeansIT{
@Inject
private lateinit var bean : UsingBean
@Test
fun canInject(){
assertThat(bean.foo()).isEqualTo("Hello World")
}
}
1)更改 UsingBean
的范围
@Service
@Scope("session")
class UsingBean{
private val scopedBean:ScopedBean
@Inject
constructor(scopedBean: ScopedBean) {
this.scopedBean = scopedBean
}
fun foo():String{
val foo = scopedBean.foo()
println(foo)
return foo
}
}
2)方法注入
@Service
class UsingBean{
private val scopedBean:ScopedBean
get() = injectBean()
fun foo():String{
val foo = scopedBean.foo()
println(foo)
return foo
}
@Lookup
fun injectBean():ScopedBean{
TODO("will be replaced by spring")
}
}
3)范围代理
@Repository
@Scope("request",proxyMode = ScopedProxyMode.TARGET_CLASS)
class RequestScopedBean : ScopedBean{
override fun foo(): String {
return "Hello World"
}
}
要么
@Repository
@RequestScope
class RequestScopedBean : ScopedBean{
override fun foo(): String {
return "Hello World"
}
}
尽管您可能认为自己没有最新的请求和会话,但实际上确实有一个。
@WebAppConfiguration
是触发它的原因。 它将激活ServletTestExecutionListener
,它将注册一个线程绑定的ServletTestExecutionListener
请求和响应。
这就解释了为什么在存在线程绑定请求的情况下测试成功的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.