Если я попытаюсь внедрить 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], у меня все равно не будет ни сеанса, ни запроса, когда я создаю экземпляр UsingBean
.
Что касается [2] и [3], они избегают получения экземпляра при запуске, но у меня все еще нет запроса, когда они действительно получают экземпляр.
И все же тест не проходит. Почему?
ПРИМЕР КОДА
Допустим, у меня есть боб в области запроса
@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) Scoped Proxy
@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"
}
}