Spring MVC Scoped Bean依赖关系和竞争条件

时间:2011-02-18 09:39:08

标签: java multithreading spring spring-mvc

由于缺乏弹簧知识,我对范围bean依赖性有一些严重的怀疑。

我已经阅读了3.5.4.5作为依赖关系的Scoped bean的参考手册,并已成功实现了一个例子。

然而,在进一步发展之前,我想分享我的担忧。

让我分享一下我的用例和一些实现细节

对于每个用户请求,我想为每个用户创建一个城市。

@Configuration
public class CityFactory{

   @Bean(name = {"currentCity" , "loggedInCity"})
   @Scope(value = WebApplicationContext.SCOPE_REQUEST,proxyMode = ScopedProxyMode.TARGET_CLASS)
   @Autowired
   public CityBean getCityBean(HttpServletRequest request) {
      return CityUtil.findCityWithHostName(request.getServerName());
   }

对于每个请求,我想将此城市注入单一作用域控制器,该控制器是控制器的默认作用域。

@RequestMapping("/demo")
@Controller
public class DemoController {

    @Autowired
    CityBean city;

    @RequestMapping(value = "/hello/{name}", method = RequestMethod.GET)
    public ModelAndView helloWorld(@PathVariable("name") String name, Model model) {
        Map<String, Object> myModel = new HashMap<String, Object>();
        model.addAttribute("hello", name);
        model.addAttribute("test", "test in " + city.getDomainName() + "  !!!    ");

        return new ModelAndView("v3/test", "m", model);
    }
}

我的问题:

1)有竞争条件吗?我担心上下文切换会在多请求环境中破坏我的应用程序。

2)我知道另一种解决方案,即每个请求创建一个控制器,但它比当前解决方案更容易出错。因为另一个开发人员可以忘记范围控制器来提出请求。

如何让控制器全局请求范围?只是因为不太好奇。

...谢谢

2 个答案:

答案 0 :(得分:0)

没有竞争条件 - 每个请求都有自己的线程

但我认为有一种更简单的方法可以做你想做的事。您可以拥有CityBean

@Service
public class CityBean {
    public String getDomainName(String serverName) {
        // obtain the name based on the server name
    }
}

在你的控制器中:

  • @Autowired CityBean bean
  • HttpServletRequest作为参数传递给方法,然后调用cityBean.getDomainName(request.getServerName());

(如果你使用一些ORM,也许你会有一个City实体,你可以获取和传递,只要小心懒惰的集合)

答案 1 :(得分:0)

这里没有竞争条件。

这是范围代理的重点 - 注入CityBean的{​​{1}}实例是一个代理,它将其方法的调用委托给DemoController的实际请求绑定实例,以便每个请求都使用自己的CityBean

我同意你不应该让控制器本身请求范围 - 这会让其他人感到困惑,因为它不是Spring MVC应用程序中的典型方法。

你也可以按照Bozho的方法建议并完全摆脱请求范围的bean,尽管这种方法有一个缺点,因为它要求你在控制器方法中添加额外的参数。