7.2. Contexts and Dependency Injection を使用したアプリケーションの開発
コンテキストと依存関係の注入 (CDI: Contexts and Dependency Injection) を使用すると、アプリケーションの開発、コードの再利用、デプロイメント時または実行時のコードの調整、およびユニットテストを非常に柔軟に行うことができます。
Weld にはアプリケーション開発の特別なモードが含まれています。有効にすると、Contexts and Dependency Injection アプリケーションの開発を容易にする特定の組み込みツールを利用できます。
アプリケーションのパフォーマンスに悪影響を与えるため、開発モードは本番環境では使用しないでください。必ずデプロイメントモードを無効にしてから本番環境にデプロイしてください。
Web アプリケーションに対して開発モードを有効にするには、以下を行います。
Web アプリケーションの場合、サーブレット初期化パラメーター org.jboss.weld.development
を true
に設定します。
<web-app> <context-param> <param-name>org.jboss.weld.development</param-name> <param-value>true</param-value> </context-param> </web-app>
管理 CLI を使用して JBoss EAP に対して開発モードを有効にするには、以下を行います。
development-mode
属性を true
に設定すると、デプロイされたアプリケーションすべてに対して Weld 開発モードをグローバルに有効にすることが可能です。
/subsystem=weld:write-attribute(name=development-mode,value=true)
7.2.1. デフォルトの Bean 検出モード
bean アーカイブのデフォルトの bean 検出モードは annotated
です。このような bean アーカイブは implicit bean archive
と呼ばれます。
bean 検出モードが annotated
の場合:
-
bean defining annotation
がなく、セッション bean の bean クラスでない bean クラスが検出されません。 - セッション bean 上になく、bean クラスが bean 定義アノテーションを持たないプロデューサーメソッドが検出されません。
- セッション bean 上になく、bean クラスが bean 定義アノテーションを持たないプロデューサーフィールドが検出されません。
- セッション bean 上になく、bean クラスが bean 定義アノテーションを持たないディスポーザーメソッドが検出されません。
- セッション bean 上になく、bean クラスが bean 定義アノテーションを持たないオブザーバーメソッドが検出されません。
Contexts and Dependency Injection セクションのすべての例は、検出モードが all
に設定されている場合にのみ有効です。
bean 定義アノテーション
bean クラスは bean defining annotation
を持つことがあり、bean アーカイブで定義されたようにアプリケーションのどこにでも配置することができます。bean 定義アノテーションを持つ bean クラスは暗黙的な bean と呼ばれます。
bean 定義アノテーションのセットには以下のものが含まれます。
-
@ApplicationScoped
、@SessionScoped
、@ConversationScoped
および@RequestScoped
アノテーション - その他すべての通常スコープタイプ。
-
@Interceptor
および@Decorator
アノテーション。 -
@Stereotype
付けられたアノテーションなど、stereotype アノテーションすべて。 -
@Dependent
スコープアノテーション。
これらのアノテーションのいずれかが bean クラスで宣言された場合、その bean クラスは bean 定義アノテーションを持っていることになります。
例: bean 定義アノテーション
@Dependent public class BookShop extends Business implements Shop<Book> { ... }
他の JSR-330 実装および Jakarta Contexts and Dependency Injection 仕様との互換性を確保するために、@Dependent
を除くすべての擬似スコープアノテーションは bean 定義アノテーションではありません。ただし、pseudo-scope アノテーションを含む stereotype アノテーションは bean 定義アノテーションです。
7.2.2. スキャンプロセスからの Bean の除外
除外フィルターは、Bean アーカイブの beans.xml
ファイルの <exclude>
要素によって <scan>
要素の子として定義されます。デフォルトでは、除外フィルターはアクティブです。定義に以下のものが含まれる場合、除外フィルターは非アクティブになります。
-
name
属性を含む、<if-class-available>
という名前の子要素。 Bean アーカイブのクラスローダーはこの名前のクラスをロードできません。 -
name
属性を含む、<if-class-not-available>
という名前の子要素。 Bean アーカイブのクラスローダーはこの名前のクラスをロードできます。 -
name
属性を含む、<if-system-property>
という名前の子要素。 この名前に対して定義されたシステムプロパティーはありません。 -
name
属性と値属性を含む、<if-system-property>
という名前の子要素。 この名前とこの値に対して定義されたシステムプロパティーはありません。
フィルターがアクティブな場合、タイプは検出から除外され、以下のいずれかの状態になります。
- 検出されるタイプの完全修飾名が、除外フィルターの名前属性の値に一致します。
- 検出されるタイプのパッケージ名が、除外フィルターの接尾辞 ".*" を含む名前属性の値に一致します。
- 検出されるタイプのパッケージ名が、除外フィルターの接尾辞 ".*" を含む名前属性の値で始まります。
例7.1 例: beans.xml
ファイル
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"> <scan> <exclude name="com.acme.rest.*" /> 1 <exclude name="com.acme.faces.**"> 2 <if-class-not-available name="javax.faces.context.FacesContext"/> </exclude> <exclude name="com.acme.verbose.*"> 3 <if-system-property name="verbosity" value="low"/> </exclude> <exclude name="com.acme.ejb.**"> 4 <if-class-available name="javax.enterprise.inject.Model"/> <if-system-property name="exclude-ejbs"/> </exclude> </scan> </beans>
- 1
- 最初の除外フィルターにより、
com.acme.rest
パッケージ内のすべてのクラスが除外されます。 - 2
- 2 番目の除外フィルターにより、
com.acme.faces
パッケージとすべてのサブパッケージ内のすべてのクラスが除外されます (Jakarta Server Faces が利用可能でない場合のみ)。 - 3
- 3 番目の除外フィルターにより、システムプロパティー
verbosity
が値low
を持つ場合に、com.acme.verbose
パッケージ内のすべてのクラスが除外されます。 - 4
- 4 番目の除外フィルターにより、システムプロパティー
exclude-ejbs
が任意の値で設定され、javax.enterprise.inject.Model
クラスがクラスローダーでも利用可能な場合に、com.acme.ejb
パッケージとすべてのサブパッケージ内のすべてのクラスが除外されます。
Jakarta EE コンポーネントに @Vetoed
アノテーションを付けて Java EE コンポーネントが Bean と見なされないようにすることができます。イベントは @Vetoed
アノテーションが付けられたタイプに対して実行されず、また @Vetoed
アノテーションが付けられたパッケージでは実行されません。詳細は @Vetoed
を参照してください。
7.2.3. インジェクションを使用した実装の拡張
インジェクションを使用して、既存のコードの機能を追加または変更できます。
この例では、既存のクラスに翻訳機能を追加します。こメソッド buildPhrase
を持つ Welcome
クラスがすでにあることを前提とします。buildPhrase
メソッドは、都市の名前を引数として取得し、Welcome to Boston! などのフレーズを出力します。
この例では、想像上の Translator
オブジェクトが Welcome
クラスにインジェクトされます。Translator
オブジェクトは、文をある言語から別の言語に翻訳できる Enterprise Java Bean ステートレス Bean または別のタイプの Bean になります。この例では、Translator
は挨拶全体を翻訳するために使用され、元の Welcome
クラスは変更されません。Translator
は、buildPhrase
メソッドが呼び出される前にインジェクトされます。
例: Translator bean の Welcome
クラスへのインジェクト
public class TranslatingWelcome extends Welcome { @Inject Translator translator; public String buildPhrase(String city) { return translator.translate("Welcome to " + city + "!"); } ... }