3.13. Additional Capabilities of the ApplicationContext
概要
ApplicationContextは、BeanFactoryの機能に以下が追加されている
- MessageSource (リソースバンドル)
- ResourceLoader (URLやファイルリソース)
- ApplicationListener (イベント配信)
- HierarchicalBeanFactory (コンテナ間の連携?)
3.13.1 Internationalization using MessageSource
ApplicationContextは自分に登録されているbeanをなめてMessageResourceを実装したものからリソースを集めてくる。Springのデフォルトでの実装は、ResourceBundleMessageSource とStaticMessageSource。
ResourceBundleMessageSource
リソースバンドルです。
<beans>
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>format</value>
<value>exceptions</value>
<value>windows</value>
</list>
</property>
</bean>
</beans>basenameに指定したリソース名でリソースバンドルが読み込まれる。こんな感じだね。
# in exceptions.properties
argument.required=The '{0}' argument is required.StaticMessageSource
殆ど使わない。プログラムから指定MessageSourceは外からはこう使う。
public static void main(String[] args) {
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
String message = resources.getMessage("message", null, "Default", null);
System.out.println(message);
}MessageSourceをインジェクションもできます。当然。ちなみにReloadableResourceBundleMessageSource というのもあるらしい。リロードするんだろうね・・
3.13.2 Standard and Custom Events
ApplicationContextにイベントが配信されると、該当するコンテナに登録されたApplicationListenerを実装するBeanが全部呼び出される。
#これ強力だなぁ。。。基本的なイベント:
- ContextRefreshedEvent :コンテキストが初期化もしくはrefleshされたあと。ちなみに厳密にはsingletonのBean初期化フックが呼ばれたあとくらい?
- ContextStartedEvent :コンテキスト開始後。Lifecycleが呼ばれた後くらい?
- ContextStoppedEvent :コンテキスト終了後。
- ContextClosedEvent :コンテキスト破棄後。singletonが全部破棄された後。
- RequestHandledEvent :HTTPリクエストの処理が終わった後で呼ばれる。
#TODO:ライフサイクルをもうちょっと掘り下げること
自分独自のカスタムイベントも作れます!
public class BlackListEvent extends ApplicationEvent {
private final String address;
private final String test;public BlackListEvent(Object source, String address, String test) {
super(source);
this.address = address;
this.test = test;
}// accessor and other methods...
}イベント配信はこんな感じでApplicationEventPublisherを使う。
public class EmailService implements ApplicationEventPublisherAware {private List
blackList;
private ApplicationEventPublisher publisher;public void setBlackList(List
blackList) {
this.blackList = blackList;
}public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}public void sendEmail(String address, String text) {
if (blackList.contains(address)) {
BlackListEvent event = new BlackListEvent(this, address, text);
publisher.publishEvent(event);
return;
}
// send email...
}
}リスナーはこんな感じ。
public class BlackListNotifier implements ApplicationListener{ private String notificationAddress;
public void setNotificationAddress(String notificationAddress) {
this.notificationAddress = notificationAddress;
}public void onApplicationEvent(BlackListEvent event) {
// notify appropriate parties via notificationAddress...
}
}ApplicationEventPublisherを使うと、すべてのイベント処理は同期的に実施される。つまりシングルスレッドで実施される。マルチスレッドで配信する場合はApplicationEventPublisherを使ってください。
3.13.3 Convenient access to low-level resources
Chapter 4, Resourcesをみれ。
3.13.4 Convenient ApplicationContext instantiation for web applications
ContextLoaderを使うと、ApplicationContextを宣言的に生成できる。ContextLoaderの仕組みは以下の二つに分かれる。
- ContextLoaderListener
- ContextLoaderServlet
やることはどっちも一緒。サーブレットバージョンの下位互換のためにサーブレットがあるだけ。理想的なのはContextLoaderListenerを使うやり方。まぁ具体的にはこうするわけだ
contextConfigLocation
/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml
org.springframework.web.context.ContextLoaderListener
3.13.5 Deploying a Spring ApplicationContext as a J2EE RAR file
RAR(リソースアダプタ?)としてデプロイすることができる。うーん、、、そもそもRARって良く解らん