1. ホーム
  2. java

[解決済み] Java EE 6 @javax.annotation.ManagedBean vs. @javax.inject.Named vs. @javax.faces.ManagedBean

2022-10-26 02:40:25

質問

Java EE 6の仕様にちょっとした混乱があるように感じます。アノテーションのセットがいくつかあります。

私たちは javax.ejb のようなアノテーションがあります。 @Stateful@Stateless を使用してEJBを作成します。

また @javax.annotation.ManagedBean を使用してマネージドビーンを作成します。

にはアノテーションがあり javax.enterprise.context のように @SessionScoped そして @RequestScoped .

さらに @ManagedBean@SessionScoped / @RequestScoped のアノテーションは javax.faces.bean パッケージで使用されます。

そして、さらに物事を複雑にするために、パッケージ javax.inject@Named のアノテーションを使用します。

どなたか、これらが互いにどのように関連しているかを説明していただけませんか?

私はどこで @EJB , @Inject または @ManagedPropery で他のビーンを注入できますか?

どのように解決するのですか?

まず最初に、いくつかの点を確認させてください。

マネージドビーンの定義 一般にマネージドビーンとは、そのライフサイクル(構築、破壊など)がコンテナによって管理されるオブジェクトのことを指します。

Java eeでは、JSFコンテナ、EJBコンテナ、CDIコンテナ、サーブレットコンテナなど、オブジェクトのライフサイクルを管理する多くのコンテナを持っています。

これらのコンテナはすべて独立して動作し、アプリケーションサーバーの初期化で起動し、デプロイ時にjar、ejb-jar、war、earファイルを含むすべての成果物のクラスをスキャンし、それらに関するいくつかのメタデータを収集し保存して、実行時にクラスのオブジェクトが必要になると、それらのクラスのインスタンスを与え、仕事を終えた後はそれらを破壊します。

というわけで、私たちは

  • JSFマネージドビーン
  • CDIマネージドビーン
  • EJBマネージドビーン
  • そして、サーブレットでさえも、コンテナによってインスタンス化され、破棄されるため、マネージドビーンです。

ですから、Managed Beanという単語を見たら、その文脈や種類を聞くべきです(JSF、CDI、EJBなど)。

では、なぜこのようなコンテナがたくさんあるのかと思うかもしれません。AFAIKは、Java EEの人たちは依存性注入フレームワークを持ちたかったのですが、彼らは将来の要件を予測できなかったので、すべての要件を1つの仕様に集めることができず、EJB 1.0、2.0、3.0と現在3.1を作っています。

同時に(並行して)JSFもサポートする必要があることに気づき、JSFマネージドビーンズとJSFビーンズ用の別のコンテナを作り、それを成熟したDIコンテナと考えたが、まだ完全で成熟したコンテナではなかった。

その後、Gavin Kingと他の素晴らしい人たちがCDIを作りました。CDIは(Seam2、Guice、Springに触発されて)JSFとEJBの間のギャップを埋めるために作られ、pojoインジェクション、プロデューサーメソッド、インターセプター、デコレーター、統合SPI、非常に柔軟など、多くの役に立つものを含んでいます。しかし、後方互換性と政治的な理由で、Java EEはそれらを維持したいのです!

ここでは、それぞれのタイプの違いとユースケースを紹介します。

JSFマネージドビーン、CDIビーン、EJB

JSFは当初、独自のマネージドBeanと依存性注入メカニズムで開発されましたが、JSF 2.0ではアノテーションベースのBeanを含むよう強化されました。CDIがJava EE 6でリリースされたとき、それはそのプラットフォームのためのマネージドBeanフレームワークとみなされ、もちろん、EJBは10年をはるかに超えて存在しているため、それらをすべて追い越しました。

もちろん、問題は、どれを使うか、そしていつ使うかを知ることです。

最も単純な、JSFマネージドビーンズから始めましょう。

JSFマネージドビーン

要するに、もしあなたがJava EE 6のために開発し、CDIを使用しているならば、これらを使用しないでください。JSFマネージドビーンは、依存性注入とWebページのバッキングビーンを定義するための簡単なメカニズムを提供しますが、CDIビーンよりもはるかに強力ではありません。

これらは @javax.faces.bean.ManagedBean アノテーションを使用して定義することができ、オプションの名前パラメータを取ります。この名前は、JSFページからBeanを参照するために使用することができます。

で定義された異なるスコープの1つを使用して、ビーンにスコープを適用することができます。 javax.faces.bean パッケージで定義された異なるスコープを使用してビーンに適用することが可能で、 リクエスト、セッション、アプリケーション、ビュー、カスタムスコープが含まれます。

@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
    ....
    ....
}

JSFのBeanは、何らかの手動コーディングなしに他の種類のBeanと混在させることはできません。

CDIビーン

CDI は Java EE 6 の一部としてリリースされた Bean 管理および依存性注入フレームワークであり、完全で包括的なマネージド Bean 機能を含んでいます。CDIビーンズは、単純なJSF管理ビーンズよりもはるかに高度で柔軟です。インターセプター、会話スコープ、イベント、タイプセーフインジェクション、デコレーター、ステレオタイプ、プロデューサーメソッドを利用することができます。

CDIビーンを配備するには、クラスパスのMETA-INFフォルダーにbeans.xmlと呼ばれるファイルを配置する必要があります。一度これを行うと、パッケージ内のすべてのビーンがCDIビーンになります。CDI には多くの機能があり、ここで取り上げるには多すぎますが、JSF のような機能のクイックリファレンスとして、CDI ビーンのスコープは javax.enterprise.context パッケージで定義されたスコープ (すなわち、リクエスト、会話、セッション、およびアプリケーションのスコープ) のいずれかを使用して CDI Bean のスコープを定義します。JSF ページから CDI Bean を使用したい場合、CDI Bean に名前を付けるには、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マネージドビーンよりもはるかに優れた選択肢となっています。

EJB

EJBはCDIビーンより先に開発され、ある意味ではCDIビーンに似ていますが、他の意味では非常に異なっています。主に、CDIビーンズとEJBの違いは、EJBは:

  • トランザクション
  • リモートまたはローカル
  • ステートフル Bean を無効化し、リソースを解放することができます。
  • タイマーを使用することができます。
  • 非同期が可能

EJBにはステートレス(stateless)とステートフル(stateful)という2つのタイプがあります。ステートレス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によって処理されます。この例外として、CDI はリモート EJB の注入をサポートしていませんが、 それはそれのための簡単なプロデューサーメソッドを書くことによって 実装することができます。

javax.inject.Named アノテーションと同様に Qualifiers を EJB で使用して、注入ポイントにマッチさせることができます。

いつどのビーンを使うか

どのビーンをいつ使うか、どうやって知るのでしょうか?簡単です。

サーブレットコンテナで作業していて、TomcatでCDIを動作させることを試したくない場合(そのためのいくつかのMavenアーキタイプがあるので言い訳はできませんが)、JSFマネージドBeanは決して使用しないでください。

一般的には、トランザクション機能などEJBで利用できる高度な機能が必要でない限り、CDI Beanを使用すべきです。CDI Beanをトランザクションにするために独自のインターセプターを書くことはできますが、今のところ、CDIがトランザクションCDI Beanを手に入れるまで、EJBを使う方がシンプルです。サーブレットコンテナから抜け出せず、CDIを使用している場合、手書きのトランザクションか、独自のトランザクションインターセプターが、EJBなしの唯一の選択肢となります。

を使う必要がある場合 @ViewScoped を使う必要がある場合、CDIでは

  • 使用 縫い目 または マイフェイスCODI モジュールのいずれかをクラスパスに追加して @ViewScoped はCDIで動作します。MyFaces CODIは@ViewScopedをさらに強固にサポートしています。
  • は、MyFaces CODIの @ViewAccessScoped は、Apache による CDI の上に書かれた拡張機能であり、単に ダウンロード をダウンロードし @ViewAccessScoped アノテーションの代わりに @ViewScoped .
  • CDIを使用する @ConversationScoped を使い、ロングランさせる。参照 をご覧ください。 .
  • 使用方法 オムニフェーズ ViewScopedアノテーション

いくつかの部分は ここから .