2

我正在阅读《Spring in Action》,上面写着“Spring 中的单例 bean 通常不维护状态,因为它们通常在多个线程之间共享”,但在我看来,Spring 中的 bean 是 POJO,那么如何它不能保持状态吗?

4

4 回答 4

3

我正在阅读《Spring in Action》,上面写着“Spring 中的单例 bean 通常不维护状态,因为它们通常在多个线程之间共享”,但在我看来,Spring 中的 bean 是 POJO,那么如何它不能保持状态吗?

是的,最好让 Spring/Singleton 没有状态(当然它可以使用其他 Spring/Singleton [它们也没有状态]),这样您就可以从不同的线程调用它的方法,而不必担心它们会弄乱它的状态(它没有一个:-))。让我们考虑一个将其中间结果存储在内部堆栈中的计算器,如果两个线程同时尝试计算某些东西会发生什么?

Spring/Singleton 被注释(如果不是,它就像它一样)并且存在于 spring context 中,它不是 POJO。

如果你想拥有一个带有状态的 Spring/Bean,你必须使用范围“原型”,每次你得到一个 bean 时,你都会得到一个不同的实例。

抱歉英语不好

于 2013-08-13T09:23:37.097 回答
2

这本书暗示,由于另一个线程对其状态的操作,bean 的状态在给定的时间点可能不可信。如果多个线程正在访问一个 bean 的同一个实例,您无法确定在使用 bean 之前发生了哪些状态更改。由于 SpringSingletons默认使用,因此只有一个 bean 实例。如果多个线程同时访问 bean,则 bean 的状态可能会出现问题。

因此,您认为 bean 将保持状态是正确的,但是由于其他线程的修改,该状态可能不可靠。

于 2013-08-13T09:06:32.937 回答
0

在典型的 Web 应用程序中,您有多个线程(每个请求一个)并且所有请求都使用相同的 bean。在典型的分层应用程序中,他们将使用Controller,然后使用Service,然后使用Repository。所有这些 bean 都应该是没有任何状态的单例。否则,您将因并发而出现错误(例如,一个线程修改单例中的数据,而另一个线程执行相同操作)。

我认为您的误解来自于说Spring 中的 bean 是 POJO。大多数 Spring bean 都是无状态 bean,我不会将其描述为 POJO。

于 2013-08-13T09:43:31.137 回答
0

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
    }
}
于 2013-08-13T11:20:32.553 回答