首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Spring组件类必须是线程安全的

Spring组件类必须是线程安全的
EN

Stack Overflow用户
提问于 2013-05-28 22:59:27
回答 3查看 30K关注 0票数 36

如果你使用Spring,你的组件类(@Controller@Service@Repository)必须是线程安全的吗?还是Spring以线程安全的方式使用它们,这样您就不必担心线程安全了?

也就是说,如果我的@Controller中有一个@RequestMapping方法,那么多个线程可以同时为同一个控制器对象调用该方法吗?

(这里有sort-of been asked before,但没有回答)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-05-28 23:13:44

给定的

代码语言:javascript
复制
@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()

如果您有实例字段,如

代码语言:javascript
复制
@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类必须是线程安全的。您可以通过为您的类实例字段使用不同的作用域,或者只使用局部变量来实现这一点。如果做不到这一点,您将需要在代码中的关键部分添加适当的同步。

票数 55
EN

Stack Overflow用户

发布于 2013-05-28 23:03:35

是的,当然。

最好是它们是无状态的,这使得它们在默认情况下是线程安全的。如果没有共享的、可变的状态,就没有问题。

票数 -1
EN

Stack Overflow用户

发布于 2018-02-14 21:08:54

基本上答案应该是肯定的和否定的。除非是非常严肃的原因。这并不是因为Spring会为您同步工作--它不会这样做(默认情况下,Controller是一个单例bean)。粗略的线程安全性必须保持在方法调用的过程中,但通常Servlets的机制消除了同步某些东西的必要性,因为请求在线程中执行。因此,在调用任何带有@RequestMapping注释的方法时,整个调用堆栈都在一个线程中执行。在根目录中,它是从服务输出的-do(Get,Post..)Servlet的方法,然后处理程序映射动作,由Spring构建(例如,请参见http://www.studytrails.com/frameworks/spring/spring-mvc-handler-mappings/ http://technicalstack.com/dispatcher-servlethandlermapping-controller/ )。在URL解析之后,Spring调用处理程序映射中的处理方法。没别的把戏了。想象一下,你在一个doPost(...)中工作。例如DispatchServlet的方法。Servlet线程安全吗?不是粗糙的。你能做到线程安全吗?是的,使用锁,同步,还有什么,让你的Servlet成为瓶颈!控制器也是如此。Servlet的doGet/Post/其他方法基本上都有一个功能模型,所有数据都在HttpServletRequest对象中。在Controller对象使用的数据类和堆栈而不是字段中应该使用相同的方式。您可以同步对它们的访问,但要付出瓶颈的代价。粗略的你可以使用原子,它是如此的必要吗?如果你需要在会话期间保持任何状态,你可以在@Controller之后使用@Scope(" session "),或者(对于单例控制器)使用带有签名(...,HttpSession)的处理程序方法,这两种方法各有优缺点。但请注意,您创建了额外的CPU和GC开销。无论如何,当您想要使用字段并退出无状态概念时,您需要对控制器线程安全负责。通常情况下,缓存(例如redis)更适合客户端状态保留。至少您可以在发生故障时恢复状态。会话作用域之外的有状态控制器基本上没有任何理由。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16795303

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档