如果你使用Spring,你的组件类(@Controller
,@Service
,@Repository
)必须是线程安全的吗?还是Spring以线程安全的方式使用它们,这样您就不必担心线程安全了?
也就是说,如果我的@Controller
中有一个@RequestMapping
方法,那么多个线程可以同时为同一个控制器对象调用该方法吗?
(这里有sort-of been asked before,但没有回答)。
发布于 2013-05-28 23:13:44
给定的
@Controller
public class MyController {
@RequestMapping(value = "/index")
public String respond() {
return "index";
}
}
Spring将创建一个MyController
实例。这是因为Spring解析您的配置<mvc:annotation-driven>
,看到@Controller
(类似于@Component
)并实例化带注释的类。因为它也可以看到@RequestMapping
,所以它会为它生成一个HandlerMapping
,请参见docs here。
DispatcherServlet
接收到的任何HTTP请求都将通过之前注册的HandlerMapping
分派到此控制器实例,并在该实例上通过java反射调用respond()
。
如果您有实例字段,如
@Controller
public class MyController {
private int count = 0;
@RequestMapping(value = "/index")
public String respond() {
count++;
return "index";
}
}
count
将是一个危险,因为它可能会被许多线程修改,对它的更改可能会丢失。
您需要了解Servlet容器是如何工作的。容器实例化Spring MVC DispatcherServlet
的一个实例。容器还管理一个线程池,用于响应连接,即。HTTP请求。当这样的请求到达时,容器从池中挑选一个线程,并在该线程中执行DispatcherServlet
上的service()
方法,该方法将分派到Spring为您注册的正确@Controller
实例(从您的配置中)。
是的,Spring MVC类必须是线程安全的。您可以通过为您的类实例字段使用不同的作用域,或者只使用局部变量来实现这一点。如果做不到这一点,您将需要在代码中的关键部分添加适当的同步。
发布于 2014-04-15 19:22:20
默认情况下,控制器是单例的,因此必须是线程安全的。但是,您可以将控制器配置为请求或会话范围,即:
@Controller
@Scope("session")
public class MyController {
...
}
具有会话作用域的控制器对管理会话状态很有帮助。在Using Sessions in Spring-MVC (including "scoped-proxies")和How to get Session Object In Spring MVC中可以找到对不同模式的良好描述。其中一些模式需要请求作用域。
如果您的数据无法为每个请求计算多个数据,则请求作用域也很有用。
发布于 2013-05-28 23:03:35
是的,当然。
最好是它们是无状态的,这使得它们在默认情况下是线程安全的。如果没有共享的、可变的状态,就没有问题。
https://stackoverflow.com/questions/16795303
复制相似问题