英文:
Spring Boot Request Scoped Beans Autowired not Populated
问题
我对Spring Boot还很陌生,我只想使用它的依赖注入,而不是所有的框架,只是一些框架。我知道有其他替代方案来实现这个功能,但我想更多地了解Spring。
我正在尝试创建一个请求范围的bean,并使用常规的依赖注入来填充它。我的计划是创建一个User对象,我可以填充它以保存一些自定义的业务细节,这样可以轻松访问,使代码更清晰。
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
class MyBean {
@Autowired
lateinit var req: HttpServletRequest
@Autowired
lateinit var env: Environment
@PostConstruct
fun pc() {
println("I am constructed $this, $req, $env")
}
var a = 3
}
@RestController
class MyController {
@GetMapping("/api/xyz")
fun login(m: MyBean): Int {
println("new bean m")
return m.a
}
}
每次我访问该端点时,我看到新的对象被实例化。但是内部的依赖关系没有被自动装配,它们始终为null。我做错了什么?我需要编写一个过滤器吗?但是我怎么知道如何找到所有需要初始化该bean的端点?如果我删除请求范围,变量会被初始化。
英文:
I'm new to Spring Boot, I only like to use its dependency injection, not all its opinionated frameworks but some. I know there are other alternatives for this functionality, but I would like to learn more Spring.
I am trying to have a request scoped bean and populate it with regular dependency injection. My plan is to have some User object that I can populate hold some custom business details that is easy to access that makes code clean.
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
class MyBean {
@Autowired
lateinit var req: HttpServletRequest
@Autowired
lateinit var env: Environment
@PostConstruct
fun pc() {
println("I am constructed $this, $req, $env")
}
var a = 3
}
@RestController
class MyController {
@GetMapping("/api/xyz")
fun login(m: MyBean): Int {
println("new bean m")
return m.a
}
}
Every time I hit that endpoint, I see new objects are instantiated. However the inner dependencies are not autowired, they are always null. What am I doing wrong? Do I need to write a filter? But how would I know how to find all the endpoints that needs that bean to be initialized? If, I remove the request scope the variables are initialized.
答案1
得分: 1
RestControllers
就像 Components
或 Services
一样是bean。所以在所有这些情况下,你应该以相同的方式处理注入的依赖项。
谈到你要添加的示例,bean 不应该是实际端点映射的参数。请求特定信息,如标头、路径变量或负载主体,适用于端点映射方法参数。
对于你的类 MyBean
的 bean 实例,你应该更倾向于直接注入成员变量或通过你的 MyController
构造函数注入(其中基于构造函数的注入是推荐的方法)。
当在 MyController
的构造函数中注入你的 MyBean
(它是 RequestScoped
)时,请不要感到困惑:这是完全有意的,并且有效。Spring 实际上会注入一个代理实例,一旦请求到达控制器调用,它将解析为请求特定的实例。
英文:
RestControllers
are beans like Components
or Services
. So in all of these you should deal with injected dependencies the same way.
Coming to the example you were adding, beans should not be parameters of actual endpoint mappings. Asking for request specific information like headers, path variables or the payload body are candidates for endpoint mapping method arguments.
For a bean instance of your class MyBean
you should rather use a member variable injected directly or via the constructor of your MyController
(where constructor based injection is the recommended approach).
Don't be confused when injecting your MyBean
which is RequestScoped
in the constructor of MyController
: this is totally intended and works. Spring actually injects a proxy instance that will resolve to the request specific instance once your request is reaching the controller invocation.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论