简体   繁体   English

Spring RequestScope bean 未按预期工作

[英]Spring RequestScope bean not working as expected

I'm trying to learn more about Spring bean scopes for use in a project.我正在尝试了解有关在项目中使用的 Spring bean 范围的更多信息。 I've created a few test classes, and I am not getting the behavior I'd expect.我创建了一些测试类,但没有得到我期望的行为。

I created the following component, and I would like this bean to last for only the duration of the HTTP request.我创建了以下组件,我希望这个 bean 只在 HTTP 请求的持续时间内持续。

@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserDataContainer {
    
    public int requestCount = 0;

}

The following controller uses that component.以下控制器使用该组件。

@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";
    }

}

My trouble is, it doesn't seem that a new instance of UserDataContainer is created for each request.我的问题是,似乎没有为每个请求创建一个新的 UserDataContainer 实例。 Whenever I load this page, I see that the values of "prev" and "curr" keep incrementing, instead of resetting to 0 at the start of each request.每当我加载此页面时,我都会看到“prev”和“curr”的值不断增加,而不是在每个请求开始时重置为 0。 Am I misunderstanding how this is supposed to work, or is something not implemented correctly.我是否误解了这应该如何工作,或者没有正确实施。

The issue here is that the request scoped bean is not invoked directly by your controller.这里的问题是请求范围的 bean 不是由您的控制器直接调用的。

Instead the controller uses a proxy to invoke the request scoped bean (in this case, the proxy is a cglib one based on your proxy mode annotation, ie: ScopedProxyMode.TARGET_CLASS相反,控制器使用代理来调用请求范围的 bean(在这种情况下,代理是一个基于您的代理模式注释的 cglib,即: ScopedProxyMode.TARGET_CLASS

The proxy only wraps around methods of the request scoped bean and not it's variables.代理只包装请求范围 bean 的方法,而不是它的变量。

So in short, encapsulate the instance variable of your request scoped bean into a method and call that method from the Controller.简而言之,将请求作用域 bean 的实例变量封装到一个方法中,然后从 Controller 调用该方法。

something like this:像这样:

@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;
   }
} 

then in your Controller, just invoke the public methods然后在您的控制器中,只需调用公共方法

@GetMapping
public String get(Model model) {
    model.addAttribute("prev", userData.getRequestCount());

    model.addAttribute("curr", userData.incrementRequestCount());
    
    return "test";
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM