java - Spring RequestScope bean 未按预期工作
问题描述
我正在尝试了解有关在项目中使用的 Spring bean 范围的更多信息。我创建了一些测试类,但没有得到我期望的行为。
我创建了以下组件,并且我希望这个 bean 仅在 HTTP 请求期间持续存在。
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserDataContainer {
public int requestCount = 0;
}
以下控制器使用该组件。
@Controller
@RequestMapping("/hello")
public class HelloController {
@Autowired
private UserDataContainer userData;
@GetMapping
public String get(Model model) {
model.addAttribute("prev", userData.requestCount);
userData.requestCount++;
model.addAttribute("curr", userData.requestCount);
return "test";
}
}
我的麻烦是,似乎没有为每个请求创建一个新的 UserDataContainer 实例。每当我加载此页面时,我都会看到“prev”和“curr”的值不断增加,而不是在每个请求开始时重置为 0。我是否误解了这应该如何工作,或者没有正确实施。
解决方案
这里的问题是请求范围的 bean 不是由您的控制器直接调用的。
相反,控制器使用代理来调用请求范围的 bean(在这种情况下,代理是基于您的代理模式注释的 cglib 代理,即:ScopedProxyMode.TARGET_CLASS
代理只包装请求范围 bean 的方法,而不是它的变量。
所以简而言之,将请求范围 bean 的实例变量封装到一个方法中,然后从 Controller 调用该方法。
像这样的东西:
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserDataContainer {
private int requestCount = 0;
public int incrementRequestCount(){
requestCount++;
return requestCount;
}
public int getRequestCount(){
return requestCount;
}
}
然后在您的控制器中,只需调用公共方法
@GetMapping
public String get(Model model) {
model.addAttribute("prev", userData.getRequestCount());
model.addAttribute("curr", userData.incrementRequestCount());
return "test";
}
推荐阅读
- python - def 分配成员(x1,x2,中心)
- swiftui - SwiftUI 导航回到第一个屏幕
- javascript - 如果条件类似于 Javascript,则 Python 一行
- kotlin - 如何在 Kotlin 中提供嵌套集合?
- flutter - 如何在 Flutter (Dart) 中通过新路由获取子级 StreamProvider 数据
- python - 用Pygame做游戏,用NEAT教一个AI,但是pygame一下子什么都画不出来
- c - ARMv8a 中这个简单的分页是如何工作的
- c# - 在 asp.net Web 表单面板属性中使用 FileUpload?
- python - 如何计算 1 和下一个 0 之间的天数
- c - 识别 UIelement 的窗口句柄和窗口名称的问题