[英]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.