Java EE 6チュートリアル は次のように述べています。
パフォーマンスを向上させるために、次のいずれかの特性がある場合は、ステートレスセッションBeanを選択できます。
- Beanの状態には、特定のクライアントのデータがありません。
- 単一のメソッド呼び出しで、Beanはすべてのクライアントに対して一般的なタスクを実行します。たとえば、ステートレスセッションBeanを使用して、オンライン注文を確認する電子メールを送信できます。
- BeanはWebサービスを実装します。
シングルトンセッションBeanは、次の状況で適切です。
- 状態はアプリケーション全体で共有する必要があります。
- 単一のエンタープライズBeanには、複数のスレッドから同時にアクセスする必要があります。
- アプリケーションには、アプリケーションの起動時とシャットダウン時にタスクを実行するためのエンタープライズBeanが必要です。
- BeanはWebサービスを実装します。
しかし、次の場合に使用するもの:
たとえば、次のインターフェイスを備えたログインサービスがあるとします。
public interface LoginService {
boolean authenticate(String user, String password);
}
@Singletonまたは@Statelessでアノテーションを付ける必要がありますか?一方と他方の利点は何ですか? LoginServiceにEntityManager(同時に使用される)を注入する必要がある場合はどうなりますか?
追加:ステートレスシングルトンであるSpringサービスBeanのJava EE対応物について考えています。 Java EEの対応物は@ステートレスセッションBeanであり、@ Singleton Beanは、起動時またはシャットダウン時のクリーンアップ時のアプリケーションの構成、またはアプリケーション全体のオブジェクトの保持に使用されることを正しく理解してください。これは正しいですか?
私はステートレスを選びます-サーバーはBeanの多くのインスタンスを生成し、着信要求を並行して処理できます。
シングルトンは潜在的なボトルネックのように聞こえます。デフォルトの@Lock値は@Lock(WRITE)ですが、Beanまたは個々のメソッドでは@Lock(READ)に変更される場合があります。
ejb 3.1仕様、110ページ、4.8.5章「シングルトン同時実行」によると:
同時アクセスをサポートしないJava EEオブジェクト(エンティティマネージャー、ステートフルセッションBean参照など)をシングルトンBeanインスタンス状態に格納することは合法です。ただし、Bean開発者は次のことを行う責任があります。このようなオブジェクトが一度に複数のスレッドからアクセスされないようにしてください。
さらに、 hibernate entitymanagerドキュメント によると
EntityManagerは、安価でスレッドセーフではないオブジェクトであり、単一のビジネスプロセス、単一の作業単位に対して1回使用してから、破棄する必要があります。
私にとって、これは、EntityManagerをシングルトンEJBに挿入してはならないことを意味します。このクラスに実装する必要があるすべてのものが追加のロック/同期を行う必要なしに同時実行をサポートする場合にのみ、ステートレスEJBの代わりにシングルトンEJBを使用します。あなたや他のプログラマーは遅かれ早かれあなたの焦点からこの問題を失うかもしれないので、私は個人的に、スタートアップ関連の問題や自己完結型のユニットとして実装できる機能を除いて、シングルトンEJBを使用しないことを好みます-他のBeanとは無関係です。その意味で、たとえばステートレスEJBをシングルトンに注入することはお勧めできません。そうすることで、コンテナが実際にシングルトンへのSLSBの注入を実行する時点についての疑問が生じますか? EJB 3.1仕様の4.8章によると、依存性注入は、クライアントがシングルトンBeanインスタンスにアクセスする前に実行されます。したがって、シングルトンは明らかにSLSBの同じインスタンスに固執し、暗黙的にシングルトンになるように見えますが、それを保証するものではないようです。少なくとも仕様には何も見つからなかったので、動作は予測できないか、最良の場合はコンテナ固有である可能性があります。これはほとんどの人が望んでいることではありません。
したがって、シングルトンをシングルトンに注入するか、シングルトンをSLSBに注入するだけで、その逆は行いません。シングルトンをシングルトンに注入する場合、仕様は、コンテナがシングルトンを正しい順序で初期化できるように、シングルトン間の依存関係を定義する機会を提供します(ejb 3.1仕様、4.8.1章を参照してください。 @DependsOnアノテーション)。
@Stateless
を使用すると、JVM内で複数のコピーを処理できるようになります(メモリとプールのサイズが許す限り)。@ Singletonの場合、JVMにはコピーが1つしかないため、単一のコピーが複数の同時スレッドをサポートできます。それ。
パフォーマンスの観点から@Singleton
使用するリソースが長時間のアクセスを許可する場合は、より良いでしょう。ただし、分散環境では、悪いことが発生することがあります。データベースまたはネットワークリンクが失敗する可能性があります。
とともに @Stateless
Bean、アクセスはより短命です。さらに、障害が発生した場合は、リスポーンしてリソースへの新しい接続を確立しようとします。シングルトンでそのようなことが起こった場合、@ PostConstructはJVMごとに1回しか呼び出されないため、アプリケーションを再起動せずに処理できるのはシングルトンです。
特に私が制御できないシステムでは、ほとんどの状況でパフォーマンスよりもフォールトトレランスを少し優先したいと思います。
並行性の使用におけるシングルトンは、SLSBプールよりもパフォーマンスが低下することはなく、さらに優れている可能性があると思います。唯一の問題は、スレッド間で何かを共有したい場合、それをロックする必要があることです。これは、パフォーマンスの大きな問題になる可能性があります。したがって、その場合、SLSBプールのパフォーマンスははるかに向上します。100%シングルトンではないため、インスタンスが多くなり、一方がロックされ、もう一方が起動します。とにかく、ロックがすべてのSLSBによるリソース共有にある場合、プールはどちらも役に立ちません。
つまり、シングルトンはSLSBプールよりも優れていると思います。可能であれば、シングルトンを使用する必要があります。これは、SpringBeansのデフォルトのスコープでもあります。
私はJavaEEの専門家ではありません。それは私の気持ちです。間違っている場合は、訂正してください。
スレッド間で状態を共有していないことが確実な場合は、シングルトンで問題ありません。その場合は、クラスに@ConcurrencyManagement( ConcurrencyManagementType.BEAN )
アノテーションを付けて、複数のスレッドを同時に実行できるようにする必要があります。
アプリケーション全体で一定に保たれるリソースがある場合は、シングルトンを選択する必要があります。アプリケーションのライフサイクル全体で変更されないファイルまたは参照データからデータをロードするようなものです。それ以外の場合は、SLSBを選択してください。 SLSBの欠点は、複数のオブジェクトが作成されるため、より多くのメモリが占有されることです。
シングルトンセッションBeanを使用する必要があると思います。ログインサービスはグローバルサービスである必要があり、具体的なユーザーや呼び出しの状態を保存する必要がないためです。
私はそのように答えます:
「アプリケーション間で状態を共有する必要はありません」という文が原因で、ステートレスBeanになります。「パフォーマンスを向上させるには、ステートレスセッションBeanを選択できます...」。
「単一のエンタープライズBeanに複数のスレッドから同時にアクセスできる」ことを考えると、シングルトンを使用する必要があります。正しく使用すれば、ステートレスBeanに同時にアクセスすることさえできません。
「起動時やショットダウン時のタスクを実行する必要はありません」は私には関係ありません。 Beanを適切にセットアップするためにタスクを実行する必要がある場合は、@ PostActivateメソッドによってタスクを呼び出す必要があります。
同時アクセスを要求したので、@ Singletonに何を使用するかについての質問を論理的に結論付けます。もちろん、それ以降のリソース(EJBではない)へのアクセスの同期を手動で制御する必要があります。