まず、いくつかの説明をさせてください:
管理対象Beanの定義:一般に、管理対象Beanは、そのライフサイクル(構築、破棄など)がコンテナによって管理されるオブジェクトです。
Java eeには、JSFコンテナー、EJBコンテナー、CDIコンテナー、サーブレットコンテナーなど、オブジェクトのライフサイクルを管理する多くのコンテナーがあります。
これらのコンテナはすべて独立して動作し、アプリケーションサーバーの初期化で起動し、展開時にjar、ejb-jar、war、earファイルを含むすべてのアーティファクトのクラスをスキャンし、オブジェクトに関するメタデータを収集して保存します。実行時のクラスの場合、それらはそれらのクラスのインスタンスを提供し、ジョブの終了後にそれらを破棄します。
だから私たちは私たちが持っていると言うことができます:
- JSF管理Bean
- CDI管理Bean
- EJB管理Bean
- また、サーブレットも、サーブレットコンテナーであるコンテナーによってインスタンス化および破棄されるため、マネージドBeanです。
したがって、マネージドBeanの単語が表示されたら、そのコンテキストまたはタイプについて質問する必要があります(JSF、CDI、EJBなど)。
次に、なぜこれらのコンテナーの多くがあるのかと尋ねるかもしれません:AFAIK、Java EEの連中は依存関係注入フレームワークが必要でしたが、将来の要件を予測できず、EJB 1.0を作成したため、1つの仕様ですべての要件を収集できませんでした。 2.0から3.0、そして現在は3.1ですが、EJBのターゲットは、いくつかの要件(トランザクション、分散コンポーネントモデルなど)のみでした。
同時に(並行して)、彼らはJSFもサポートする必要があることに気づき、JSFマネージドBeanとJSF Beanの別のコンテナーを作成し、成熟したDIコンテナーと見なしましたが、それでも完全で成熟したコンテナーではありませんでした。
その後、Gavin Kingと他の素敵な人たち;)が、私が見た中で最も成熟したDIコンテナであるCDIを作成しました。CDI(Seam2、Guice、Springに触発された)は、JSFとEJBの間のギャップを埋めるために作られました。pojoインジェクション、プロデューサーメソッド、インターセプター、デコレーター、統合SPI、非常に柔軟なものなど、他にもたくさんあります。 EJBとJSFマネージドBeanが実行していることは、成熟した強力なDIコンテナを1つだけ持つことができるということです。しかし、いくつかの下位互換性と政治的な理由から、Java EEの人たちはそれらを保持したいと考えています!!!
ここでは、これらの各タイプの違いとユースケースを見つけることができます。
JSF管理Bean、CDI Bean、およびEJB
JSFは当初、独自のマネージドBeanと依存性注入メカニズムを使用して開発されましたが、アノテーションベースのBeanを含めるようにJSF 2.0用に拡張されました。CDIがJava EE 6とともにリリースされたとき、CDIはそのプラットフォームのマネージドBeanフレームワークと見なされていました。もちろん、EJBは10年以上も昔から存在していました。
もちろん問題は、どれを使うか、いつ使うかを知ることです。
最も単純なJSF管理Beanから始めましょう。
JSFマネージドBean
つまり、Java EE 6向けに開発しており、CDIを使用している場合は、これらを使用しないでください。これらは、依存性注入とWebページのバッキングBeanを定義するための単純なメカニズムを提供しますが、CDI Beanよりもはるかに強力ではありません。
これら@javax.faces.bean.ManagedBean
は、オプションの名前パラメーターを取るアノテーションを使用して定義できます。この名前は、JSFページからBeanを参照するために使用できます。
スコープjavax.faces.bean
は、リクエスト、セッション、アプリケーション、ビュー、カスタムスコープなど、パッケージで定義されたさまざまなスコープの1つを使用してBeanに適用できます。
@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
....
....
}
JSF Beanは、何らかの手動コーディングがなければ、他の種類のBeanと混合できません。
CDI Bean
CDIは、Java EE 6の一部としてリリースされたBean管理および依存性注入フレームワークであり、完全で包括的な管理対象Bean機能が含まれています。CDI Beanは、単純なJSF管理Beanよりもはるかに高度で柔軟性があります。インターセプター、会話スコープ、イベント、タイプセーフインジェクション、デコレーター、ステレオタイプ、プロデューサーメソッドを利用できます。
CDI Beanをデプロイするには、クラスパスのMETA-INFフォルダーにbeans.xmlというファイルを配置する必要があります。これを実行すると、パッケージ内のすべてのBeanがCDI Beanになります。CDIには多くの機能があり、ここではカバーしきれませんが、JSFのような機能のクイックリファレンスとして、javax.enterprise.context
パッケージで定義されたスコープの1つ(つまり、リクエスト、会話)を使用してCDI Beanのスコープを定義できます。、セッション、アプリケーションのスコープ)。JSFページからCDI Beanを使用する場合は、javax.inject.Named
アノテーションを使用して名前を付けることができます。Beanを別のBeanに挿入するには、フィールドにjavax.inject.Inject
注釈を付けます。
@Named("someBean")
@RequestScoped
public class SomeBean {
@Inject
private SomeService someService;
}
上記で定義したような自動注入は、注入したい特定のクラスに一致させるのに役立つ修飾子を使用して制御できます。複数の支払いタイプがある場合は、非同期かどうかの修飾子を追加できます。@Named
アノテーションは修飾子として使用できますが、ELでBeanを公開するために提供されているため、使用しないでください。
CDIは、プロキシを使用して、スコープが一致しないBeanの注入を処理します。このため、リクエストスコープのBeanをセッションスコープのBeanに注入できます。また、リクエストごとにプロキシがリクエストスコープのBeanのライブインスタンスに再接続するため、参照は各リクエストで引き続き有効です。
CDIは、インターセプター、イベント、新しい会話スコープ、およびJSF管理対象Beanよりもはるかに優れた機能となる他の多くの機能もサポートしています。
EJB
EJBはCDI Beanよりも古く、CDI Beanにいくらか似ていますが、他の点では非常に異なります。主に、CDI BeanとEJBの違いは、EJBは次のとおりです。
- トランザクション
- リモートまたはローカル
- ステートフルBeanをパッシベーションしてリソースを解放できる
- タイマーを利用できる
- 非同期にすることができます
2種類のEJBは、ステートレスとステートフルと呼ばれます。ステートレスEJBは、2つのWebリクエスト間で状態を維持しないスレッドセーフな使い捨てBeanと考えることができます。ステートフルEJBは状態を保持し、破棄されるまで必要に応じて作成および保存できます。
EJBの定義は簡単で、クラスにjavax.ejb.Stateless
またはjavax.ejb.Stateful
アノテーションを追加するだけです。
@Stateless
public class BookingService {
public String makeReservation(Item Item, Customer customer) {
...
...
}
}
ステートレスセッションBeanは任意のスコープを持つことができますが、ステートレスBeanは依存するスコープを持つ必要があります。デフォルトではトランザクションですが、トランザクション属性アノテーションを使用できます。
EJBとCDI Beanの機能は非常に異なりますが、CDI BeanはEJBに注入でき、EJBはCDI Beanに注入できるため、それらを統合するコードの記述は非常に似ています。片方をもう片方に注入する場合、区別する必要はありません。この場合も、さまざまなスコープは、プロキシを使用してCDIによって処理されます。これの1つの例外は、CDIがリモートEJBのインジェクションをサポートしていないことですが、それは簡単なプロデューサーメソッドを記述することで実装できます。
javax.inject.Named
任意修飾子ならびに注釈は注入点に一致するようにEJBに使用することができます。
どのBeanをいつ使用するか
どのBeanをいつ使用するかはどのようにしてわかりますか?シンプル。
サーブレットコンテナーで作業していて、TomcatでCDIを動作させたくない場合を除いて、JSF管理Beanを使用しないでください(ただし、Mavenアーキタイプがいくつかあるため、言い訳はありません)。
一般に、トランザクション機能などのEJBで利用可能な高度な機能が必要でない限り、CDI Beanを使用する必要があります。独自のインターセプターを作成してCDI Beanをトランザクション対応にすることができますが、現時点では、CDIがすぐ近くにあるトランザクション対応のCDI Beanを取得するまで、EJBを使用する方が簡単です。サーブレットコンテナでスタックし、CDIを使用している場合は、EJBを使用しない場合は、手書きのトランザクションまたは独自のトランザクションインターセプタが唯一のオプションです。
@ViewScoped
CDIで使用する必要がある場合は、
- seam-facesまたはMyFaces CODIモジュールを使用します。それらの1つをクラスパスに追加するだけ
@ViewScoped
で、CDIで動作します。MyFaces CODIは、@ ViewScopedをさらに強力にサポートしています。
- MyFaces CODIを使用します
@ViewAccessScoped
。これは、ApacheによってCDIの上に記述された拡張機能です。それをダウンロードして、の@ViewAccessScoped
代わりに注釈を使用してください@ViewScoped
。
- CDI
@ConversationScoped
を使用して長時間実行します。詳細はこちらをご覧ください。
- Omnifaces @ViewScopedアノテーションを使用する
ここから一部盗難。