7.4. 管理 Bean
Java EE では管理対象 Bean 仕様の共通定義が確立されています。管理対象 bean は、プログラミングの制限が最小限であるコンテナー管理オブジェクトとして定義され、POJO (Plain Old Java Object) として知られるようになりました。管理対象 bean はリソースのインジェクション、ライフサイクルコールバック、インターセプターなどの基本サービスの小さなセットをサポートします。EJBや CDI などのコンパニオン仕様は、この基本モデルに基づいて構築されます。
ごくわずかな例外を除き、パラメーターのないコンストラクター (または @Inject
アノテーションが指定されたコンストラクター) を持つ具象 Java クラスは bean になります。これには、すべての Java Bean と EJB セッション bean が含まれます。
7.4.1. Bean であるクラスのタイプ
管理対象 bean は Java クラスです。管理対象 bean の基本的なライフサイクルやセマンティクスは、管理対象 Bean の仕様で定義されています。bean クラス @ManagedBean
アノテーションを付けることで明示的に管理対象 bean を宣言できますが、CDI ではその必要はありません。この仕様によると、CDI コンテナーでは、以下の条件を満たすクラスはすべて管理対象 bean として扱われます。
- 非静的な内部クラスではないこと。
-
具象クラス、あるいは
@Decorator
アノテーションが付与されている。 -
EJB コンポーネントを定義するアノテーションが付与されていないこと、あるいは
ejb-jar.xml
ファイルで EJB bean クラスとして宣言されていること。 -
インターフェース
javax.enterprise.inject.spi.Extension
を実装しないこと。 -
パラメーターのないコンストラクターか、
@Inject
アノテーションが付与されたコンストラクターがあること。 -
@Vetoed
アノテーションが付いていないこと、または@Vetoed
アノテーションが付けられたパッケージ内にないこと。
管理対象 bean の無制限の bean 型には、直接的あるいは間接的に実装する bean クラス、スーパークラスすべて、およびインターフェースすべてが含まれます。
管理対象 Bean にパブリックフィールドがある場合は、デフォルトの @Dependent
スコープが必要です。
@Vetoed
@Vetoed
アノテーションは CDI 1.1 で導入されました。このアノテーションを追加することにより、Bean をインジェクションから除外できます。
@Vetoed public class SimpleGreeting implements Greeting { ... }
このコードでは、SimpleGreeting
Bean はインジェクションの対象となりません。
パッケージ内のすべての bean をインジェクションから除外できます。
@Vetoed package org.sample.beans; import javax.enterprise.inject.Vetoed;
org.sample.beans
パッケージ内の package-info.java
のこのコードにより、このパッケージ内のすべての Bean がインジェクションから除外されます。
ステートレス EJB や JAX-RS リソースエンドポイントなどの Java EE コンポーネントには、bean と見なされないように @Vetoed
を付けることができます。@Vetoed
アノテーションをすべての永続エンティティーに追加すると、BeanManager
がエンティティーを CDI Bean として管理しないようになります。エンティティーに @Vetoed
アノテーションが付けられた場合は、インジェクションが行われません。これは、JPA プロバイダーの破損原因となる操作を BeanManager
が実行しないようにするためです。
7.4.2. CDI を用いたオブジェクトの Bean へのインジェクト
CDI コンポーネントがアプリケーションで検出されると、CDI は自動的にアクティベートされます。デフォルト値と異なるよう設定をカスタマイズする場合は、デプロイメントアーカイブに META-INF/beans.xml
ファイルまたは WEB-INF/beans.xml
ファイルを含めることができます。
他のオブジェクトにオブジェクトをインジェクトする
クラスのインスタンスを取得するには、bean 内でフィールドに
@Inject
アノテーションを付けます。public class TranslateController { @Inject TextTranslator textTranslator; ...
インジェクトしたオブジェクトのメソッドを直接使用します。
TextTranslator
にメソッドtranslate
があることを前提とします。// in TranslateController class public void translate() { translation = textTranslator.translate(inputText); }
Bean のコンストラクターでインジェクションを使用します。ファクトリーやサービスロケーターを使用して作成する代わりに、Bean のコンストラクターへオブジェクトをインジェクトできます。
public class TextTranslator { private SentenceParser sentenceParser; private Translator sentenceTranslator; @Inject TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) { this.sentenceParser = sentenceParser; this.sentenceTranslator = sentenceTranslator; } // Methods of the TextTranslator class ... }
Instance(<T>)
インターフェースを使用してインスタンスをプログラムにより取得します。Bean 型でパラメーター化されると、Instance
インターフェースはTextTranslator
のインスタンスを返すことができます。@Inject Instance<TextTranslator> textTranslatorInstance; ... public void translate() { textTranslatorInstance.get().translate(inputText); }
オブジェクトを Bean にインジェクトすると、Bean は全オブジェクトのメソッドとプロパティーを使用できるようになります。Bean のコンストラクターにインジェクトするときに、インジェクションがすでに存在するインスタンスを参照する場合以外は、Bean のコンストラクターが呼び出されるとインジェクトされたオブジェクトのインスタンスが作成されます。たとえば、セッションの存続期間内にセッションスコープの Bean をインジェクトしても、新しいインスタンスは作成されません。