这个Spring单例bean线程的设计是否安全?

hap*_*s10 24 java concurrency singleton spring multithreading

考虑以下Spring Service类.定义的弹簧范围是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
Run Code Online (Sandbox Code Playgroud)

说DocumentService类是不可变的是正确的,因为它不可能改变它的两个字段中的任何一个(可以通过容器本身只初始化一次的spring bean)?

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

Mr.*_*art 20

说DocumentService类是不可变的是正确的,因为它不可能改变它的两个字段中的任何一个(可以通过容器本身只初始化一次的spring bean)?

根据不变性定义,并且从形式上讲,这个类不是不可变的.

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

并且,因此,如果类始终具有相同的状态,则其行为始终相同.换句话说,没有办法改变不可变对象的行为,因为对象的行为只取决于它的状态,而在不可变对象中,这个状态永远不会改变(不可变对象的例子是字符串和整数).

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

有一种策略可以使类不可变.你已经遵循了它的一些指导原则,但是如果你希望它是不可变的(我认为不是这种情况)你需要其他一些像你在构造函数中获得的参数的"防御性复制"避免子类重写方法.

这个链接也很有趣.

不过,你不应该让Spring bean不可变,因为它不是使用Spring提供的编程模型的方法.因此,在这种情况下,该类不是不可变的"好".

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

如此处所声明的,此类是IS线程安全的.许多线程可以安全地访问此类,而不会出现任何竞争条件.我们不能对它包含的字段说同样的内容,但这个类是线程安全的.这与"线程安全列表"的工作方式相同:它可以包含"无线程安全"对象,但仍然是"线程安全列表".

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

如果系统的所有类都是线程安全的(即不会出现单个竞争条件),您可以非正式地说应用程序是线程安全的.