弹簧组件类必须是线程安全的

2022-09-01 03:51:59

如果使用 Spring,组件类 (, 、 ) 必须是线程安全的吗?或者Spring是否以线程安全的方式使用它们,因此您不必担心线程安全?@Controller@Service@Repository

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

(这个问题以前问过,但没有这样回答)。


答案 1

鉴于

@Controller
public class MyController {
    @RequestMapping(value = "/index")
    public String respond() {
        return "index";
    }
}

Spring 将创建一个 .这是因为 Spring 解析您的配置,,看到(类似于 )并实例化带注释的类。因为它也看到,它为它生成一个,请参阅此处的文档MyController<mvc:annotation-driven>@Controller@Component@RequestMappingHandlerMapping

接收的任何HTTP请求都将通过之前注册的实例调度到此控制器实例,并通过该实例上的java反射进行调用。DispatcherServletHandlerMappingrespond()

如果您有实例字段,例如

@Controller
public class MyController {
    private int count = 0;
    @RequestMapping(value = "/index")
    public String respond() {
        count++;
        return "index";
    }
}

count这将是一个危险,因为它可能会被许多线程修改,并且对它的更改可能会丢失。

您需要了解 Servlet 容器的工作原理。容器实例化了 Spring MVC 的一个实例。容器还管理一个线程池,用于响应连接,即。HTTP 请求。当这样的请求到达时,容器从池中选取一个 Thread,并在该 Thread 中执行该方法,该方法调度到 Spring 为您注册的正确实例(从您的配置中)。DispatcherServletservice()DispatcherServlet@Controller

所以是的,Spring MVC类必须是线程安全的。为此,您可以为类实例字段使用不同的作用域,或者只使用局部变量。如果做不到这一点,则需要在代码中的关键部分周围添加适当的同步。


答案 2

是的,当然。

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


推荐