《Spring in Action》を読んでいると、「Spring のシングルトン Bean は通常、複数のスレッド間で共有されるため、状態を維持しないことが多い」と書かれていますが、私の意見では、Spring の Bean は POJO です。状態を維持できませんか?
4 に答える
《Spring in Action》を読んでいると、「Spring のシングルトン Bean は通常、複数のスレッド間で共有されるため、状態を維持しないことが多い」と書かれていますが、私の意見では、Spring の Bean は POJO です。状態を維持できませんか?
はい、Spring/Singleton には状態がない方が良いです (もちろん、他の Spring/Singleton を使用することもできます [状態のないものも])。そのため、状態が台無しになることを心配することなく、異なるスレッドからそのメソッドを呼び出すことができます。 (それはありません:-))。内部スタック内に中間結果を格納する電卓について考えてみましょう。2 つのスレッドが同時に何かを計算しようとするとどうなるでしょうか?
Spring/Singleton には注釈が付けられており (注釈が付けられていない場合はそのままです)、Spring コンテキスト内に存在します。これは POJO ではありません。
状態を持つ Spring/Bean が必要な場合は、スコープ「プロトタイプ」を使用する必要があります。この種のスコープでは、Bean を取得するたびに差分インスタンスが取得されます。
下手な英語でごめんなさい
Spring Bean は、Spring で使用するために特別な要件 (特定のインターフェースを実装する、特定のクラスを拡張する、何らかの方法で特定するなど) に従う必要がないという意味で POJO と見なされます。
要件によっては、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 とは少し異なります。
class SomeOtherClass {
public void process() {
// gets called from another object
Situation z = new Situation();
z.handle();
// other processing
}
}
典型的な Web アプリケーションでは、複数のスレッド (リクエストごとに 1 つ) があり、すべてのリクエストが同じ Bean を使用しています。典型的な階層化されたアプリケーションでは、Controllerを使用し、次にServiceを使用し、次にRepositoryを使用します。これらの Bean はすべて、状態のないシングルトンである必要があります。そうしないと、並行性によるバグが発生します (たとえば、あるスレッドがシングルトンのデータを変更し、別のスレッドが同じことを行うなど)。
あなたの誤解は、Spring の Bean が POJO であると言っていることに起因すると思います。Spring Bean のほとんどはステートレス Bean であり、POJO とは言いません。