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


107

Java EE 6仕様には少し混乱があると思います。アノテーションにはいくつかのセットがあります。

我々は持っているjavax.ejbような注釈@Stateful@StatelessEJBを作成するために。

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

javax.enterprise.contextlike @SessionScopedとに注釈があります@RequestScoped

さらに、パッケージ内に@ManagedBeanand @SessionScoped/ @RequestScopedアノテーションがありjavax.faces.beanます。

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

誰かがそれらが互いにどのように関連しているかを誰かが説明できますか?

どこで@EJB@Injectまたは@ManagedPropery他の豆を注入できますか?


回答:


194

まず、いくつかの説明をさせてください:

管理対象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を使用しない場合は、手書きのトランザクションまたは独自のトランザクションインターセプタが唯一のオプションです。

@ViewScopedCDIで使用する必要がある場合は、

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

ここから一部盗難。


3
これは素晴らしい!ありがとう!完全にするために、CDIまたはEJB BeanをJSF Beanに注入する方法を指示してください。ある@ManagedProperty("#{someBean})"適切な方法?
Piotr Gwiazda 2012

2
違う!動作しません。ただCDIにあなたのJSF管理対象Beanを回して使用して注釈を付けることによってBeanを管理@Namedし、@javax.enterprise.context.RequestScopedかつ@Injectアノテーションを使用CDI注入を使用します。;)する必要がない場合は、jsf管理Beanを使用しないでください。
Mehdi 2012

3
> JEEの人たちはそれを守りたいのです!!! -それより少し微妙です。CDIはJava EE 6サイクルのかなり遅い時期に終了し、JSF 2とJAX-RSはすでに完了しています。彼らはrespを強化しました。独自の管理Bean機能をすでに導入しています。CDIが少し前に利用可能であった場合、状況は異なって見える可能性があります。Java EE 7では、JSFはCDIを採用し、javax.faces.beanは最終的に非推奨になります(非推奨はJava EEでは遅いプロセスですが、これは良い面と悪い面の両方です)。
Arjan Tijms 2012

3
CDI Beanをデプロイするには、クラスパスのMETA-INFフォルダーにbeans.xmlというファイルを配置する必要があります。これを実行すると、パッケージ内のすべてのBeanがCDI Beanになります。すべてのBeanは、それが何であったかに加えて、CDI Beanになるということですか?ManagedBeanとViewScopedを備えたJSF ManagedBeansがある場合はどうなりますか?まだJSFマネージドBeanですか?
Koray

3
この素晴らしい記事で誰かがJava EE 7のアップデートを行うことができますか?
Martijn Burger 2014

7

うん、これは混乱する可能性があります。

いくつかのためにEHM歴史的な理由JSFとCDIスコープの同じアノテーションを使用しますが、別のパッケージからしています。

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

優れた溶接ドキュメントの最初の数ページ(またはそれ以上)を読み飛ばすことをお勧めします。これにより、Java EE 6に順調に進むはずです。

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


実際、私には2つの質問があります。1。ビューのスコープが非常に役立つことがよくあります。JSFアノテーションを使用する必要がありますか?2.これは、@javax.annotation.ManagedBeanCDIがすべてのクラスをマネージドBeanとして扱うので役に立たないことを意味しますね。
Piotr Gwiazda 2012

結構です。Seam Facesなどを使用して、JSFスコープをCDIにブリッジする必要があります。そして、はい、関連するjarファイルにbeans.xmlがある場合、@ ManagedBeansは必要ありません。ああ、さらに質問がある場合は、コメントセクションで自分を失う前に、新しいスレッドを開始することをお勧めします。
jan groth 2012

3

特にについての返信はないため@javax.annotation.ManagedBean、同様の質問の回答へのリンクを次に示します。バッキングBean(@ManagedBean)またはCDI Bean(@Named)?。仕様はhttp://download.oracle.com/otndocs/jcp/managed_beans-1.0-fr-eval-oth-JSpec/にあります。したがって、それは@javax.annotation.ManagedBeanの一般化を意図したものであるように見え@javax.faces.bean.ManagedBeanます。

私が収集したものから、JSFマネージドBeanはCDI Beanに代わり段階的に廃止されています(おそらくJSF 2.3から非推奨になっているのでしょうか?)@javax.annotation.ManagedBean


@Named@ManagedBean将来的に置き換えられますか?
Thufir 2014年

1
たとえば、stackoverflow.com / questions / 4347374 /…のように、CDI @NamedBeanがJSF @ManagedBeansに取って代わると予測するさまざまなJava EE専門家の声明をいくつか読んだことがあります。 EE 8.」
HeinBlöd2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.