- 4.1. ApplicationContext
- 4.2. MessageSource
- 4.3. イベントの伝播
- 4.4. Web アプリケーションでの ApplicationContext の利用
4.3. イベントの伝播
Spring では標準的な Observer パターンによるイベントを伝播する機能があり、この機能は ApplicationContext、ApplicationEvent クラス、ApplicationListener インタフェースにより提供されます。Observer パターンでは Observer (観察者) と Subject (被験者) が存在しますが、Spring においては ApplicationContext (正確には ApplicationEventMulticaster ) が Subject、ApplicationListener インタフェースが Observer となります。ApplicationContext は ApplicationListener インタフェースを実装した JavaBeans (Observer) がコンテナに登録されているときイベント発生時に毎回 Observer にイベント通知を行います。イベント発生時には ApplicationContext に定義されている以下のメソッドで通知します。
public void publishEvent(ApplicationEvent event)
ApplicationEvent を継承した独自のイベントを作成することもできますが Spring ではあらかじめ以下のイベントが用意されており、それぞれ以下のようなタイミングで発行されます。
イベント | 説明 |
---|---|
ContextRefreshedEvent | ApplicationContext が初期化またはリフレッシュされたときに発行されます。 |
ContextClosedEvent | ApplicationContext がクローズされたときに発行されます。 |
RequestHandledEvent | Spring の DispatcherServlet を使用している Web アプリケーションにHTTP リクエストがあった場合に発行されます。 |
ここでは ContextRefreshedEvent と ContextClosedEvent が実際に発行されているかどうかを簡単なプログラムで確認してみます。Observer
となる ContextObserver は org.springframework.context.ApplicationListener インタフェースを実装します。このインタフェースで定義されている
onApplicationEvent()
メソッドのシグニチャは以下の通りです。
public void onApplicationEvent(ApplicationEvent event)
イベント発生時には Subject により onApplicationEvent()
メソッドが呼ばれます。onApplicationEvent()
メソッドは ApplicationEvent を引数にとりますので受け取ったイベントの種類により適切な処理が行われるよう実装します。
package com.techscore.spring.di; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextRefreshedEvent; public class ContextObserver implements ApplicationListener { public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ContextRefreshedEvent) { System.out.println("context is refreshed."); } else if (event instanceof ContextClosedEvent) { System.out.println("context is closed."); } } }
ContextObserver はイベントを受け取り、それが ContextRefreshedEvent
か ContextClosedEvent
であった場合それぞれ異なるメッセージを標準出力に表示します。
package com.techscore.spring.di; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { System.out.println("ApplicationContext を生成します。"); ConfigurableApplicationContext appContext = new ClassPathXmlApplicationContext("/com/techscore/spring/di/beans.xml"); System.out.println("ApplicationContext をクローズします。"); appContext.close(); } }
これを実行すると以下の結果を得ます。それぞれ適切なタイミングでイベントが発行されているのがわかります。
ApplicationContext を生成します。 context is refreshed. ApplicationContext をクローズします。 context is closed.
実習課題 2
Spring を使用して以下の要件を満たすコンソールアプリケーションを作成しなさい。
- 1秒ごとにカウントアップするメソッドを持つクラスを作成する。
- 10秒たつとカウントアップを終了しイベントを発行する。
- カウントアップ終了イベントが発行されると標準出力に何らかの表示を行うクラスを作成する。
- ヒント: カウントアップするメソッドを持つクラスは
org.springframework.context.ApplicationContextAware
インタフェースを実装する。