【问题标题】:Singleton scope in Spring BootSpring Boot 中的单例范围
【发布时间】:2018-08-28 08:20:42
【问题描述】:

所以我的问题是关于 Spring Boot 中的单例范围。我从事过一些 Spring Boot 项目,但我从未见过使用 Prototype 范围注释的类,所以我假设在 Spring Boot 中默认定义的所有 bean 都是单例的。现在假设有 2 个线程正在访问单例 bean,那么在这种情况下,我们如何确保一个线程所做的更改不会影响另一个线程在同一个 bean 上工作。

现在您可能会说我们可以进行同步,但我还没有在 Web 应用程序中看到使用同步来避免这种情况。那么spring boot究竟是如何处理这个问题的。

【问题讨论】:

  • 这其实是一个很好的问题。简短的回答:不是! Beans 应保持只读状态。如果您将它们用作全局变量(单例反模式的基本示例!),您将面临竞争条件。即使您使用原型范围,您也会面临同样的问题。或者,您可以使用其他范围,例如 request
  • 正如@BranislavLazic 已经说过的,只要您的 bean 中没有状态,单例范围就没有问题。

标签: spring spring-boot model-view-controller


【解决方案1】:

任何 bean 的默认范围确实是 Singleton。接下来,你所有的 bean 都应该被设计成无状态的。如果 bean 是无状态的,您不必担心多个线程访问同一个 Bean / 同步。因为他们的数据不会被对方修改。

无状态是什么意思?简单的解释一下,你不应该有被不同线程修改的类级字段。您的状态应该存储在会话、存储库或由您的客户端。

最后,为了澄清一些小问题,这与其说是 Spring Boot 问题,不如说是 Spring Framework / Spring MVC 问题。 Bean 范围是核心框架的一部分(Spring MVC 提供了更多范围选项)。

【讨论】:

  • 我完全同意 bean 的无状态方法。假设在 Web 应用程序中,我收到了对相同处理程序方法的 http 请求,并且我已经使用 bean 将 JSON 映射到 bean 对象。现在两个请求都在发送不同的 JSON 数据,所以在这种情况下,它是由应用程序服务器处理还是由 Spring Boot 处理?
  • 这是一个复杂的问题,首先,默认 Spring Boot Web 项目在 Web 容器 (Tomcat) 中构建。 Web 容器将处理请求并将请求传递给 Spring Boot 已经配置的“发送 servlet”。
  • despatch servlet 然后传递给您的控制器代码。每个请求都在自己的线程中运行。当两个请求进入同一个端点时,每个线程都有自己的调用堆栈,这意味着它可以在该 bean 中执行一个方法,而不会相互影响。当这些线程尝试更改存储在 bean 中的相同数据时,就会出现问题,但由于它们是无状态的,因此您可以避免该问题。
猜你喜欢
  • 2014-09-29
  • 1970-01-01
  • 1970-01-01
  • 2010-12-17
  • 1970-01-01
  • 2018-03-09
  • 1970-01-01
  • 2014-11-02
  • 1970-01-01
相关资源
最近更新 更多