Java SpringMVC范围的Bean依赖项和竞争条件
由于缺乏spring知识,我对scopebean依赖性有一些严重的怀疑 我已经阅读了参考手册3.5.4.5中作为依赖项的作用域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
@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类来自另一个遗留库。也非常感谢你的建议。