web-dev-qa-db-ja.com

Java EE 6 @ javax.annotation.ManagedBean vs. @ javax.inject.Named vs. @ javax.faces.ManagedBean

Java EE 6の仕様には少し混乱があります。いくつかの注釈セットがあります。

EJBを作成するためのjavax.ejb@Statefulなどの@Statelessアノテーションがあります。

マネージドBeanを作成する@javax.annotation.ManagedBeanもあります。

javax.enterprise.context@SessionScopedのような@RequestScopedには注釈があります。

さらに、@ManagedBeanおよび@SessionScoped/@RequestScoped注釈がjavax.faces.beanパッケージにあります。

物事をより複雑にするために、javax.injectアノテーション付きの@Namedパッケージがあります。

誰かがお互いにどのように関係しているのか説明していただけますか?

@EJB@Inject、または@ManagedProperyを使用して他のBeanを注入できますか?

105
Piotr Gwiazda

まず最初に、いくつかの説明をさせてください。

マネージド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の連中は依存性注入フレームワークを望んでいましたが、予測できないために1つの仕様ですべての要件を収集できませんでした将来の要件であり、EJB 1.0、2.0、3.0、そして3.1になりましたが、EJBのターゲットはいくつかの要件(トランザクション、分散コンポーネントモデルなど)のみでした。

同時に(並行して)JSFもサポートする必要があることに気づき、JSF管理BeanとJSF Beanの別のコンテナを作成し、成熟したDIコンテナと見なしましたが、それでも完全で成熟したコンテナではありませんでした。

その後、ギャビン・キングと他のナイスたちが;)私が見た中で最も成熟したDIコンテナであるCDIを作りました。 CDI(Seam2、Guice、Springに触発された)は、JSFとEJB、およびpojoインジェクション、プロデューサーメソッド、インターセプター、デコレーター、統合SPI、非常に柔軟なものなど、他の多くの有用なものの間のギャップを埋めるために作られました。 EJBおよびJSFマネージドBeanが実行していることにより、成熟した強力なDIコンテナを1つだけ持つことができます。しかし、いくつかの後方互換性と政治的理由のためにJava EEの人はそれらを維持したい!!!

ここでは、これらの各タイプの違いとユースケースを見つけることができます。

JSFマネージドBean、CDI BeanおよびEJB

JSFは当初、独自のマネージドBeanと依存性注入メカニズムを使用して開発され、JSF 2.0でアノテーションベースのBeanが含まれるように拡張されました。 CDIがJava EE 6でリリースされたとき、それはそのプラットフォームのマネージドBeanフレームワークと見なされていました。もちろん、EJBは10年以上も使用されていました。

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

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

JSFマネージドBean

つまり、Java EE 6で開発し、CDIを使用している場合は使用しないでください。Webページの依存性注入とバッキングBeanの定義のためのシンプルなメカニズムを提供しますが、 CDI Beanよりも強力です。

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

スコープは、リクエスト、セッション、アプリケーション、ビュー、カスタムスコープを含むjavax.faces.beanパッケージで定義されているさまざまなスコープのいずれかを使用してBeanに適用できます。

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

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

CDI Beans

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

CDI Beanをデプロイするには、beans.xmlというファイルをクラスパス上のMETA-INFフォルダーに配置する必要があります。これを行うと、パッケージ内のすべてのBeanがCDI Beanになります。 CDIには多くの機能があり、ここでは説明しきれませんが、JSFのような機能のクイックリファレンスとして、javax.enterprise.contextパッケージ(つまり、要求、会話、セッション、およびアプリケーションスコープ)。 JSFページからCDI Beanを使用する場合は、javax.inject.Named注釈を使用してCDI Beanに名前を付けることができます。 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をパッシベーションしてリソースを解放できる
  • タイマーを利用できる
  • 非同期にすることができます

EJBの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によって処理されます。これの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を使用しない唯一の選択肢は、手書きのトランザクションまたは独自のトランザクションインターセプターのいずれかです。

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

  • seam-faces または MyFaces CODI モジュールを使用します。それらの1つをクラスパスに追加するだけで、@ViewScopedはCDIで機能します。 MyFaces CODIは、@ ViewScopedをさらに強固にサポートします。
  • myFaces CODIの@ViewAccessScopedを使用します。これはApacheによってCDIの上に記述された拡張機能です。ただ download itで、@ViewAccessScopedの代わりに@ViewScopedアノテーションを使用します。
  • CDI @ConversationScopedを使用して、実行時間を長くします。 詳細はこちら を参照してください。
  • Omnifaces @ViewScopedアノテーションを使用します

here から盗み出された一部のパーツ。

189
Heidarzadeh

うん、これはわかりにくいかもしれません。

いくつかのehm歴史的な理由により、JSFとCDIはスコープに対して同じ注釈を使用していますが、異なるパッケージからのものです。

おそらく推測しているように、javax.faces.beanからのものはJSF仕様からのものであり、CDIとは関係ありません。使用する非常に正当な理由がない限り、それらを使用しないでください。また、javax.ejbのCDIアノテーションとそれらを混在させないでください。これにより、バグと微妙な異常の完全な無限リストが生成されます。

一般的に、優れた Weld documentation の最初の数ページ(またはそれ以上)を読み飛ばすことをお勧めします。これにより、Java EE 6。

さらに質問をここに投稿してください。

6
jan groth

@javax.annotation.ManagedBeanに関する具体的な回答がないため、同様の質問への回答へのリンクを次に示します。 Backing beans(@ManagedBean)またはCDI Beans(@Named)? 。仕様は http://download.Oracle.com/otndocs/jcp/managed_beans-1.0-fr-eval-oth-JSpec/ にあります。したがって、@javax.annotation.ManagedBean@javax.faces.bean.ManagedBeanを一般化することを意図していたようです。

私が集めたものから、JSF Managed BeansはCDI Beansを支持して段階的に廃止されているので(JSF 2.3から非推奨になるのでしょうか?)、@javax.annotation.ManagedBeanは今では時代遅れになっています。

1
Hein Blöd