まず、いくつかの説明をさせてください。
管理対象Beanの定義:一般に、管理対象Beanは、そのライフサイクル(構築、破棄など)がコンテナーによって管理されるオブジェクトです。
Java eeには、JSFコンテナ、EJBコンテナ、CDIコンテナ、サーブレットコンテナなど、オブジェクトのライフサイクルを管理する多くのコンテナがあります。
これらのコンテナはすべて、一種の独立した動作をします。アプリケーションサーバーの初期化で起動し、デプロイ時にjar、ejb-jar、war、earファイルを含むすべてのアーティファクトのクラスをスキャンし、それらに関するメタデータを収集して保存します。その後、オブジェクトが必要になります。実行時にクラスのインスタンスを提供し、ジョブの終了後にそれらを破棄します。
したがって、次のように言うことができます。
- JSFマネージドBean
- CDIマネージドBean
- EJB管理対象Bean
- また、サーブレットでさえ、サーブレットコンテナであるコンテナによってインスタンス化および破棄されるため、マネージドBeanです。
したがって、Managed 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つだけ持つことができます。しかし、いくつかの下位互換性と政治的な理由から、JavaEEの人たちはそれらを維持したいと思っています!!!
ここでは、これらの各タイプの違いと使用例を見つけることができます。
JSFマネージドBean、CDI Bean、およびEJB
JSFは当初、独自のマネージドBeanと依存性注入メカニズムを使用して開発されました。これは、JSF 2.0用に拡張され、アノテーションベースのBeanが含まれるようになりました。CDIがJavaEE6でリリースされたとき、それはそのプラットフォームのマネージドBeanフレームワークと見なされていました。もちろん、EJBは、10年以上前から存在していたものをすべて時代遅れにしました。
もちろん問題は、どれをいつ使用するかを知ることです。
最も単純なJSFマネージドBeanから始めましょう。
JSFマネージドBean
つまり、Java EE 6用に開発していて、CDIを使用している場合は、これらを使用しないでください。これらは、依存性注入とWebページのバッキングBeanの定義のための単純なメカニズムを提供しますが、CDIBeanよりもはるかに強力ではありません。
@javax.faces.bean.ManagedBean
これらは、オプションのnameパラメーターを受け取るアノテーションを使用して定義できます。この名前は、JSFページからBeanを参照するために使用できます。
javax.faces.bean
スコープは、リクエスト、セッション、アプリケーション、ビュー、カスタムスコープを含むパッケージで定義されたさまざまなスコープの1つを使用してBeanに適用できます。
@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
....
....
}
JSF Beanは、何らかの手動コーディングなしでは、他の種類のBeanと混合することはできません。
CDI Beans
CDIは、Java EE 6の一部としてリリースされたBean管理および依存性注入フレームワークであり、完全で包括的なマネージドBean機能が含まれています。CDI Beanは、単純なJSF管理対象Beanよりもはるかに高度で柔軟性があります。インターセプター、会話スコープ、イベント、タイプセーフインジェクション、デコレーター、ステレオタイプ、プロデューサーメソッドを利用できます。
CDI Beanをデプロイするには、beans.xmlというファイルをクラスパスのMETA-INFフォルダーに配置する必要があります。これを行うと、パッケージ内のすべてのBeanがCDIBeanになります。javax.enterprise.context
CDIには多くの機能があり、ここではカバーできませんが、JSFのような機能のクイックリファレンスとして、パッケージで定義されているスコープの1つ(つまり、要求、会話)を使用してCDIBeanのスコープを定義できます。、セッションおよびアプリケーションスコープ)。JSFページのCDIBeanを使用する場合は、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はCDIBeanよりも前のものであり、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とCDIBeanは機能の点で非常に異なりますが、CDI BeanをEJBに注入でき、EJBをCDI Beanに注入できるため、それらを統合するコードの記述は非常に似ています。一方を他方に注入するときに区別する必要はありません。この場合も、さまざまなスコープがプロキシを使用してCDIによって処理されます。これに対する1つの例外は、CDIがリモートEJBの注入をサポートしていないことですが、CDI用の単純なプロデューサーメソッドを作成することで実装できます。
javax.inject.Named
アノテーションと任意の修飾子をEJBで使用して、インジェクションポイントに一致させることができます。
どのBeanをいつ使用するか
どのBeanをいつ使用するかをどのようにして知ることができますか?単純。
サーブレットコンテナで作業していて、TomcatでCDIを動作させたくない場合を除いて、JSFマネージドBeanを使用しないでください(ただし、そのためのMavenアーキタイプがいくつかあるため、言い訳はできません)。
一般に、トランザクション関数など、EJBで使用可能な高度な機能が必要でない限り、CDIBeanを使用する必要があります。独自のインターセプターを作成してCDIBeanをトランザクション化することもできますが、今のところ、CDIがすぐ近くにあるトランザクションCDI Beanを取得するまで、EJBを使用する方が簡単です。サーブレットコンテナでスタックしていてCDIを使用している場合は、手書きのトランザクションまたは独自のトランザクションインターセプターのいずれかがEJBなしの唯一のオプションです。
@ViewScoped
CDIで使用する必要がある場合は、
- seam-facesまたはMyFacesCODIモジュールを使用します。それらの1つをクラスパスに追加するだけで
@ViewScoped
、CDIで機能します。MyFaces CODIは、@ViewScopedをさらに確実にサポートします。
- MyFaces CODIを使用します
@ViewAccessScoped
。これは、ApacheによってCDIの上に記述された拡張機能です。ダウンロード@ViewAccessScoped
して、の代わりに注釈を使用して@ViewScoped
ください。
- CDI
@ConversationScoped
を使用して、長時間実行します。詳細については、こちらをご覧ください。
- Omnifaces@ ViewScopedアノテーションを使用する
ここから一部の部品が盗まれました。