コンテナのライフサイクルイベント

前回紹介したExtentionの定義方法では、肝心の拡張モジュールの中身は空でした。今回は、拡張モジュール内でCDIコンテナとやりとりをする方法について書きます。

CDI JavaDocのjavax.enterprise.inject.spiパッケージを見ると、CDIコンテナのライフサイクルイベントのインタフェースが定義されています。CDIのコンテナはアプリケーションの初期化時に内部的に各種イベントを発行します。CDI拡張モジュールはこれらのイベントをコンテナから受信することによって拡張モジュール内部で処理を記述します。

CDIではオブジェクト間でイベントの送受信をすることができます。イベントの送信側はEventオブジェクトのfire()メソッドを呼び出します。イベント受信側はイベントを受信するメソッドのメソッドパラメーターに@Observesアノテーションをつけることによって指定した型のイベントを受信することができます(CDIイベントについてはWeldドキュメントのこのあたりを参考にしてください)。

さて、前置きはこのくらいにして本題に戻ります。次のクラスはContainerLifecycleEventsはCDIコンテナの発行するイベントを受信して標準出力にログを書くだけの単純な拡張モジュールです(代表的なイベントだけ書いています)。

package org.tanoseam.examples;

import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.*;

public class ContainerLifecycleEvents implements Extension
{
 public ContainerLifecycleEvents() {
 log("ContainerLifecycleEvents constructor");
 }

public void beforeBeanDiscovery(@Observes BeforeBeanDiscovery event) {
 log("BeforeBeanDiscovery");
 }

public void afterBeanDiscovery(@Observes AfterBeanDiscovery event,
 BeanManager bm) {
 log("AfterBeanDiscovery");
 }

public void afterDeploymentValidation(@Observes AfterDeploymentValidation event,
 BeanManager bm) {
 log("AfterDeploymentValidation");
 }

public void beforeShutdown(@Observes BeforeShutdown event,
 BeanManager bm) {
 log("BeforeShutdown");
 }

public <t> void processAnnotatedType(@Observes ProcessAnnotatedType<t> event) {
 log("ProcessAnnotatedType=" + event);
 }

public <t> void processInjectionTarget(@Observes ProcessInjectionTarget<t> event) {
 final AnnotatedType at = event.getAnnotatedType();
 log("InjectionTarget=" + at);
 }

void log(String messages) {
 System.out.println("CDI: " + messages);
 }
}

これを見ると各メソッドに@Observesがついていて、パラメータの型の名前がCDIコンテナのライフサイクルイベントであることが確認できます。例えば、最初のメソッドはBeforeBeanDiscoveryというイベントを受信します。この拡張モジュールをWeld examplesのjsf/loginに組み込んだ場合の標準出力は次のようになります。

22:42:15,150 INFO [org.jboss.weld] (MSC service thread 1-4) Processing CDI deployment: weld-login.war 
22:42:15,181 INFO [stdout] (MSC service thread 1-4) CDI: ContainerLifecycleEvents constructor 
22:42:15,665 INFO [org.jboss.weld] (MSC service thread 1-3) Starting Services for CDI deployment: weld-login.war 22:42:16,498 INFO [stdout] (MSC service thread 1-3) CDI: BeforeBeanDiscovery 
22:42:16,550 INFO [stdout] (MSC service thread 1-3) CDI: ProcessAnnotatedType=public@Entity class org.jboss.weld.examples.login.User 
22:42:16,567 INFO [stdout] (MSC service thread 1-3) CDI: ProcessAnnotatedType=public@Named @Default @RequestScoped class org.jboss.weld.examples.login.Credentials 
22:42:16,569 INFO [stdout] (MSC service thread 1-3) CDI: ProcessAnnotatedType=public abstract interface class org.jboss.weld.examples.login.UserManager 
22:42:16,592 INFO [stdout] (MSC service thread 1-3) CDI: ProcessAnnotatedType=public class org.jboss.weld.examples.login.Resources 
22:42:16,610 INFO [stdout] (MSC service thread 1-3) CDI: ProcessAnnotatedType=public@Named @Alternative @Stateful @RequestScoped class org.jboss.weld.examples.login.EJBUserManager 
22:42:16,627 INFO [stdout] (MSC service thread 1-3) CDI: ProcessAnnotatedType=public@Named @RequestScoped class org.jboss.weld.examples.login.ManagedBeanUserManager 
22:42:16,649 INFO [stdout] (MSC service thread 1-3) CDI: ProcessAnnotatedType=public@SessionScoped @Named class org.jboss.weld.examples.login.Login 
22:42:17,185 INFO [stdout] (MSC service thread 1-3) CDI: InjectionTarget=public class org.jboss.weld.examples.login.Resources 
22:42:17,205 INFO [stdout] (MSC service thread 1-3) CDI: InjectionTarget=public@SessionScoped @Named class org.jboss.weld.examples.login.Login 
22:42:17,217 INFO [stdout] (MSC service thread 1-3) CDI: InjectionTarget=public@Named @Default @RequestScoped class org.jboss.weld.examples.login.Credentials 
22:42:17,297 INFO [stdout] (MSC service thread 1-3) CDI: InjectionTarget=public@Named @RequestScoped class org.jboss.weld.examples.login.ManagedBeanUserManager 
22:42:17,320 INFO [stdout] (MSC service thread 1-3) CDI: InjectionTarget=public@Entity class org.jboss.weld.examples.login.User 
22:42:17,356 INFO [stdout] (MSC service thread 1-3) CDI: AfterBeanDiscovery 
22:42:17,439 INFO [stdout] (MSC service thread 1-3) CDI: AfterDeploymentValidation

この出力結果を見ると、

  1. 拡張モジュールのコンストラクタ
  2. BeforeBeanDiscoveryイベント
  3. ProcessAnnotatedTypeイベントの繰り返し
  4. ProcessInjectionTargetイベントの繰り返し
  5. AfterBeanDiscoveryイベント
  6. AfterDeploymentValidationイベント
の順でCDIコンテナの処理が進むことがわかります。ステップ6の後にアプリケーションの処理が開始されます。ログ上では拡張モジュールのコンストラクタは1度しか呼ばれておらず、CDIコンテナは拡張モジュールのインスタンスを維持しているだろうということが読み取れます。
拡張モジュールの処理自身は受信したイベントを使って記述します。次回は各イベントの概要について書くつもりです。
広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。