如果我尝试将请求范围的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"
}
}
答案 0 :(得分:1)
尽管您可能会认为您没有当前请求,但实际上您确实拥有一个。
@WebAppConfiguration
是触发它的原因。它将激活ServletTestExecutionListener
,后者将注册线程绑定的模拟请求和响应。
其中解释了为什么存在线程绑定请求而测试成功的原因。