Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring单例bean的这种设计是线程安全的吗?_Java_Multithreading_Spring_Concurrency_Singleton - Fatal编程技术网

Java Spring单例bean的这种设计是线程安全的吗?

Java Spring单例bean的这种设计是线程安全的吗?,java,multithreading,spring,concurrency,singleton,Java,Multithreading,Spring,Concurrency,Singleton,考虑下面的Spring服务类。定义的spring范围是Singleton。下面类中自动连接为字段的两个服务bean具有类似的结构-它们也由以下字段组成 春豆本身 无状态类 不变类 等等。此模式在应用程序设计中被全面使用 @Service public class DocumentService { private final DocumentGenerationService documentGenerationService; private final Docume

考虑下面的Spring服务类。定义的spring范围是Singleton。下面类中自动连接为字段的两个服务bean具有类似的结构-它们也由以下字段组成

  • 春豆本身
  • 无状态类
  • 不变类
等等。此模式在应用程序设计中被全面使用

@Service     
public class DocumentService {  
  private final DocumentGenerationService documentGenerationService;
  private final DocumentPublishService documentPublishService;

  @Autowired
  public DocumentService (DocumentGenerationService documentGenerationService,    
                          DocumentPublishService documentPublishService) {
  this.documentGenerationService = documentGenerationService;
  this.documentPublishService = documentPublishService;
}

... methods follow
DocumentService类是不可变的,因为它不可能改变它的两个字段中的任何一个(这是只能由容器本身初始化一次的SpringBean),这样说对吗


在任何情况下,上面定义的DocumentService bean都可以被认为是线程安全的吗?如果遵循这种设计,整个应用程序也是线程安全的?

您可以将@Autowired注释放在服务之上,而不是在构造函数中使用它们。它是一个Spring管理的bean,这意味着它是一个单体。它是线程安全的,但这取决于实现

@Service     
public class DocumentService {  

  @Autowired
  private DocumentGenerationService documentGenerationService;

  @Autowired
  private DocumentPublishService documentPublishService;

... methods follow

弹簧不能保证螺纹安全。这是你的责任

所有私有成员变量都是共享的。它们可能是最终的,但这只意味着引用不能更改。任何可变状态都必须同步。如果它们确实是不可变的,那么我认为你有坚实的基础


我同意关于自动关联依赖项的评论。如果可能的话,我会让Spring控制它们。

您问题中显示的示例代码绝对是线程安全的

但是,需要在整个应用程序的上下文中考虑代码。例如,上面的代码不能保证
documentGenerationService
documentPublishService
属性所引用对象的线程安全。如果它们没有充分同步,那么使用它们的代码(包括此类的其他方法)可能不是线程安全的

DocumentService类是不可变的,因为它不可能改变它的两个字段中的任何一个(这是只能由容器本身初始化一次的SpringBean),这样说对吗

从形式上讲,这个类不是一成不变的

如果无法更改对象的状态,则对象是不可变的,
documentGenerationService
documentPublishService
的状态是类状态的一部分

因此,如果类具有始终相同的状态,则其行为方式始终相同。换言之,无法更改不可变对象的行为,因为对象的行为仅取决于其状态,而在不可变对象中,此状态永远不会更改(不可变对象的示例为字符串和整数)

请注意,在不变性的定义中,我们发现了一个例外,即“即使某些[…]属性发生了变化,但对象的状态[因此,行为]似乎是不变的[…],但在这种情况下(提供了信息),对象也被视为不可变的”引用状态的改变肯定会改变类的行为(因为我们不能控制它们自己的内部状态)

有一个使类不可变。您已经遵循了它的一些指导原则,但是如果您希望做到不可变(我认为不是这样),您将需要一些其他的指导原则,比如对构造函数中接收到的参数进行“防御性复制”,并避免子类重写方法

这也很有趣

然而,您不应该使Springbeans不可变,因为这不是使用Spring提供的编程模型的方法。因此,在这种情况下,类不是不可变的是“好的”

在任何情况下,上面定义的DocumentService bean都可以被认为是线程安全的吗

正如这里声明的,这个类是线程安全的。许多线程可以安全地访问这个类,而不会产生任何争用条件。我们不能对它包含的字段说同样的话,但是这个类是线程安全的。这与“线程安全列表”的工作方式相同:它可以包含“无线程安全”对象,但仍然是“线程安全列表”

如果遵循这种设计,整个应用程序也是线程安全的


如果系统的所有类都是线程安全的(即,没有出现任何单一的争用条件),您可以非正式地说应用程序是线程安全的。

您的代码看起来是线程安全的。 Spring并不能保证线程安全,因为它说bean是单态的。如果您在spring中创建singleton作用域的bean,那么这仅仅意味着每个spring IoC容器创建一个对象实例。但单例作用域bean类本身可能不是线程安全的,因此它的程序员有责任使代码线程安全

例如,在您的代码中,
documentGenerationService
是最终的。这保证了引用不能更改,而且从新的Java内存模型来看,实例化也是有保证的。但是@duffymo说,被引用的对象也必须是不可变的


Rest都很好:)

Spring说bean是单态的,但它并不能保证线程安全。如果您在spring中创建singleton作用域的bean,那么这仅仅意味着每个spring IoC容器创建一个对象实例。但是,单例作用域bean类本身可能不是线程安全的,因此它的程序员有责任使代码线程安全。

@edutesoy-“…documentGenerationService和documentPublishService的状态是DocumentService类状态的一部分。”-我想你不能肯定地说。这取决于你的观点。这个问题似乎是根源