Spring对象是否安全?如果没有,如何使它们的线程安全?
答案 0 :(得分:98)
这是两个无关的问题:
没有。
Spring有不同的bean scopes(例如Prototype,Singleton等),但是当创建bean时,所有这些范围强制执行。例如,每次“注入”此bean时,都会创建一个“prototype”范围的bean,而“singleton”范围的bean将在应用程序上下文中创建一次并共享。还有其他范围,但它们只是在创建新实例时定义的时间跨度(例如“范围”)。
上面几乎没有,如果与线程安全有关,因为如果几个线程可以访问bean(无论范围),它只依赖于该bean的 design 成为或不成为“线程安全”。
我说“很少,如果有的话”的原因是因为它可能取决于你试图解决的问题。例如,如果您担心2个或更多HTTP请求是否可能为同一个bean创建问题,则会有"request" scope为每个HTTP请求创建一个bean的新实例,因此您可以“思考”特定bean在多个HTTP请求的上下文中是“安全的”。但它仍然不是Spring 真正的线程安全,因为如果有几个线程在相同的 HTTP请求中使用这个bean,它会回到bean设计(你的< / em>设计bean支持类。)
有几种方法,可能在这里列出的时间太长了,但这里有一些例子:
设计bean 不可变:例如,没有setter,只使用构造函数参数来创建bean。还有其他方法,例如Builder pattern等。
设计你的bean 无状态:例如,做的bean可以只是一个函数(或几个)。在大多数情况下,这个bean可以应该无状态,这意味着它没有任何状态,只有 每次都有你提供的函数参数(在每次调用时)
设计你的bean persistent :这是“不可变”的特例,但有一些非常好的属性。通常用于函数式编程,其中Spring(至少尚未)在命令式世界中没有用,但我已将它们与Scala / Spring项目一起使用。
使用锁设计您的bean [最后的手段]:除非您正在使用 lower 级别的库,否则我建议不要这样做。原因是我们(人类)在锁定方面并不好。就是我们养育和培养的方式。一切都是平行发生的,我们不需要“暂停下雨,让我得到一把雨伞”。然而,当你在谈论“多个事物同时”时,计算机都是关于锁的,因此我们中的一些人(特殊人)正在做他们的公平分享并基于这些锁实现库。大多数其他人只能使用这些库,而不用担心并发性。
答案 1 :(得分:2)
弹簧不保证线程安全。但是它提供了有关此事的指导方针。 如果您的bean具有状态,请不要使用单例bean作用域。
我创建了一个演示,以显示具有Singleton和Prototype范围的春豆的可变性
我专注于有状态的bean,然后使用Singleton和Prototype范围显示了bean如何改变其状态。
Job类由JobPrototype和JobSingleton Bean扩展,它们是基于活动概要文件集加载的。 TP设置配置文件,将属性spring.profiles.active设置为proto(对于原型范围)或singleton(对于Singleton范围)
活动作业Bean在Runner和Runner1 Bean中自动装配,它们具有Scheduled方法来定期更改自动装配Bean的状态
root.addEventHandler(EventType.ROOT, (Event event) -> {
if (event.getEventType().getName().equals("BranchExpandedEvent")) {
TreeItem item = (TreeItem) event.getSource();
//here I want to know item position
}
});
}
public class Job {
protected int count = 0;
void counter() {
this.count++;
}
public int getCount() {
return count;
}
结果是
此演示的完整代码beans_mutability