108

JavaEE6の仕様には少し混乱があるように感じます。注釈のセットがいくつかあります。

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

@javax.annotation.ManagedBean管理対象Beanを作成するためのもあります。

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

さらに、パッケージには/注釈も@ManagedBeanあります。@SessionScoped@RequestScopedjavax.faces.bean

そして、物事をより複雑にするために、注釈付きjavax.injectのパッケージがあります。@Named

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

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

4

3 に答える 3

194

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

管理対象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.contextCDIには多くの機能があり、ここではカバーできませんが、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なしの唯一のオプションです。

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

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

ここから一部の部品が盗まれました。

于 2012-08-17T20:20:24.907 に答える
7

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

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

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

一般的に、優れたWeldドキュメントの最初の数ページ(またはそれ以上)をざっと読むことをお勧めします。これにより、JavaEE6の軌道に乗ることができます。

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

于 2012-08-16T13:43:14.013 に答える
5

特にについての返信はないので@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はますます時代遅れになっていると思います。

于 2014-06-17T11:19:12.100 に答える