Java SpringMVC范围的Bean依赖项和竞争条件

Java SpringMVC范围的Bean依赖项和竞争条件,java,multithreading,spring,spring-mvc,Java,Multithreading,Spring,Spring Mvc,由于缺乏spring知识,我对scopebean依赖性有一些严重的怀疑 我已经阅读了参考手册3.5.4.5中作为依赖项的作用域bean,并成功地实现了一个关于它的示例 然而,在进一步讨论之前,我想与大家分享我的担忧 让我来分享一下我的用例和一些实现细节 对于每个用户请求,我想为每个用户创建一个城市。 @Configuration public class CityFactory{ @Bean(name = {"currentCity" , "loggedInCity"}) @Sco

由于缺乏spring知识,我对scopebean依赖性有一些严重的怀疑

我已经阅读了参考手册3.5.4.5中作为依赖项的作用域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);
    }
}
对于每个请求,我希望将该城市注入一个单一作用域控制器,这是控制器的默认作用域。

@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);
    }
}
@RequestMapping(“/demo”)
@控制器
公共类DemoController{
@自动连线
城市海滨城市;
@RequestMapping(value=“/hello/{name}”,method=RequestMethod.GET)
公共模型和视图helloWorld(@PathVariable(“name”)字符串名称,模型模型){
Map myModel=newhashmap();
model.addAttribute(“hello”,name);
model.addAttribute(“test”,“test in”+city.getDomainName()+“!!!”);
返回新的ModelAndView(“v3/test”,“m”,model);
}
}
我的问题是:

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

2) 我知道还有另一个解决方案,它可以为每个请求创建一个控制器,但它比当前的解决方案更容易出错。因为另一个开发人员可以忘记作用域控制器来发出请求

如何使控制器全局请求范围?只是因为有点好奇


谢谢…

无争用条件-每个请求都有自己的线程

但我认为有一种更简单的方法来做你想做的事。您可以使用您的
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
实体,你可以获取并传递它,只是要小心懒惰的集合)

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

但我认为有一种更简单的方法来做你想做的事。您可以使用您的
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
实体,你可以获取并传递它,只是要小心懒惰的集合)

这里没有竞争条件

这就是作用域代理的要点-注入
DemoController
CityBean
实例是一个代理,它将其方法的调用委托给
CityBean
的实际请求绑定实例,以便每个请求都与自己的
CityBean
一起工作

我同意您不应该将控制器本身的请求范围限定在某个范围内——这会让其他人感到困惑,因为这不是SpringMVC应用程序中的典型方法


您也可以遵循Bozho建议的方法,完全摆脱请求范围的bean,尽管这种方法有一个缺点,因为它需要您向控制器方法添加额外的参数。

这里没有竞争条件

这就是作用域代理的要点-注入
DemoController
CityBean
实例是一个代理,它将其方法的调用委托给
CityBean
的实际请求绑定实例,以便每个请求都与自己的
CityBean
一起工作

我同意您不应该将控制器本身的请求范围限定在某个范围内——这会让其他人感到困惑,因为这不是SpringMVC应用程序中的典型方法


您也可以遵循Bozho建议的方法,完全摆脱请求范围的bean,尽管这种方法有一个缺点,因为它需要您向控制器方法添加额外的参数。

CityBean类来自另一个遗留库。非常感谢您的建议。CityBean类来自另一个遗留库。也非常感谢你的建议。