我正在阅读《Spring in Action》,上面写着“Spring 中的单例 bean 通常不维护状态,因为它们通常在多个线程之间共享”,但在我看来,Spring 中的 bean 是 POJO,那么如何它不能保持状态吗?
4 回答
我正在阅读《Spring in Action》,上面写着“Spring 中的单例 bean 通常不维护状态,因为它们通常在多个线程之间共享”,但在我看来,Spring 中的 bean 是 POJO,那么如何它不能保持状态吗?
是的,最好让 Spring/Singleton 没有状态(当然它可以使用其他 Spring/Singleton [它们也没有状态]),这样您就可以从不同的线程调用它的方法,而不必担心它们会弄乱它的状态(它没有一个:-))。让我们考虑一个将其中间结果存储在内部堆栈中的计算器,如果两个线程同时尝试计算某些东西会发生什么?
Spring/Singleton 被注释(如果不是,它就像它一样)并且存在于 spring context 中,它不是 POJO。
如果你想拥有一个带有状态的 Spring/Bean,你必须使用范围“原型”,每次你得到一个 bean 时,你都会得到一个不同的实例。
抱歉英语不好
这本书暗示,由于另一个线程对其状态的操作,bean 的状态在给定的时间点可能不可信。如果多个线程正在访问一个 bean 的同一个实例,您无法确定在使用 bean 之前发生了哪些状态更改。由于 SpringSingletons
默认使用,因此只有一个 bean 实例。如果多个线程同时访问 bean,则 bean 的状态可能会出现问题。
因此,您认为 bean 将保持状态是正确的,但是由于其他线程的修改,该状态可能不可靠。
在典型的 Web 应用程序中,您有多个线程(每个请求一个)并且所有请求都使用相同的 bean。在典型的分层应用程序中,他们将使用Controller,然后使用Service,然后使用Repository。所有这些 bean 都应该是没有任何状态的单例。否则,您将因并发而出现错误(例如,一个线程修改单例中的数据,而另一个线程执行相同操作)。
我认为您的误解来自于说Spring 中的 bean 是 POJO。大多数 Spring bean 都是无状态 bean,我不会将其描述为 POJO。
Spring bean 被认为是 POJO,因为它不需要遵守与 Spring 一起使用的特殊要求(实现某些接口、扩展特定类、以某种方式具体等)。
根据要求,Spring bean 可能需要维护和操作其状态。
它还取决于考虑 Spring bean 是否应该是单例的要求。
如果单例 Spring bean 维护自己的状态,则必须采取适当的保护措施以确保正确的并发访问/修改。
混淆来自企业应用程序中使用的一般模式,其中 Spring bean 用于实现大量系统逻辑并支持操作。
在这些场景中,Spring bean 本身没有任何状态通常是一个很好的做法,它只是包含实际状态的值对象/数据传输对象的扩展。
由于这些 Spring bean 不会保持自己的状态,因此它们几乎总是被创建为单例。
SomeClass
,SomeOtherClass
并且Situation
都是下面代码中的 POJO。
SomeClass
并且SomeOtherClass
是 Spring bean 但Situation
不是,这是一个 DTO。
class SomeClass {
private int x; // not restricted
public void handleSituation(Situation s) {
// may or may not use/modify SomeClass state represented by 'x'
// one approach is to provide all required information through parameters
}
}
class SomeOtherClass {
@Autowired
private SomeClass sc;
public void process() {
// gets called from another object
Situation z = new Situation();
sc.handleSituation(z);
// other processing
}
}
<!-- default scope = singleton -->
<bean id="someClassBean" class="SomeClass"/>
<bean id="someOtherClassBean" class="SomeOtherClass">
<property name="someClass" ref="someClassBean"/>
</bean>
这与纯 OOP 略有不同,纯 OOP 的代码类似于以下代码。
class SomeOtherClass {
public void process() {
// gets called from another object
Situation z = new Situation();
z.handle();
// other processing
}
}