Spring Framework 入門記 Contextその1 ApplicationContext
今回は「3.9 Introduction to the ApplicationContext」です.長かったbeans
パッケージをついに卒業して,ここからはcontext
パッケージです.進歩するって気持ちいいですね〜.というわけで,improvement.jp
なんていうマイドメインをメールアドレスに使っています.
さてcontext
パッケージですが,これはbeans
パッケージの上位に位置付けられて,BeanFactory
の機能をframework-styleなアプローチに与えてくれる... らしいです.英語むずいな*1.Springもframeworkだよね? って一瞬思いましたが,ここでいうフレームワークはプレゼンテーションフレームワークなどを意識しているようです... たぶん.それで,ContextLoader
というweb
なパッケージに入っているクラスなどを使うと,これまで愛用してきたXmlBeanFactory
をプログラマチックに扱わなくてもいいとか.うーん,なんだかよく分かりません.
分からないときはソースを見れるのがオープンソースのいいところ.というわけでちょっとApplicationContext
を見てみると,これはBeanFactory
をextends
したインタフェースなんですね.なぁんだ,それなら怖くないぞ!
ではそのApplicationContext
,BeanFactory
にどんな能力を付加してくれているのでしょうか? ドキュメントによると,
- 国際化対応のメッセージにアクセスできます.
- URLやファイルなどのリソースにアクセスできます.
- イベントを伝播してくれます.
- 複数のコンテキストをロードできます.
... 悪くはないし,真っ当なアプリケーションでは必要なのでしょうが,ちょっと魅力に乏しい感じ.
まぁ,いいでしょう.一つずつやっていきましょう.
ApplicationContext
はBeanFactory
でもあることが分かったので,まずはこれまで遊んできたサンプルをApplicationContext
対応に変更してみることにします.
... むぅ.
このドキュメント,ApplicationContext
を使ったコードがないなぁ.3章の中にはまったく出てこないぞ.自分で調べろってか? いいでしょう.そんなときはソースを見られるのがオープンソースのいいところ.おっ,FileSystemXmlApplicationContext
なるクラスを発見! 名前は物々しいけれど,要するにXMLの定義ファイルを読み込んでくれるらしい.
ということで,まずは実行用クラスの
XmlBeanFactory factory = new XmlBeanFactory(new FileInputStream("beans.xml"));
を
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("beans.xml");
に変更します.コンストラクタの引数は文字列なので,自分でInputStream
にしなくてもいいんですね.ちょっとだけラクチン?
そして変数factory
をcontext
に置換します.
おやぁ? BeanFactory
のカスタマイズのところで,postProcessBeanFactory
の呼び出しがエラーに? なるほど,postProcessBeanFactory
の引数は以前も書いたようにConfigurableListableBeanFactory
なのですが,ApplicationContext
はListableBeanFactory
とHierarchicalBeanFactory
をextends
しているだけなんですね.じゃあカスタマイズはどうするんだろう? ようやくBigDecimal
を使えるようになったのに,どうするんだろう? そんなときはソースを見れるのが(以下略).
なるほどー,ApplicationContext
は,初期化中に自分をカスタマイズしてくれるんですね.プログラマチックに扱わなくてもいいっていうのはそういうことかぁ.
ということで,カスタマイズ用(CustomEditorConfigurer
やPropertyPlaceholderConfigurer
)の定義も一緒にApplicationContext
に与えてあげればいいようです.FileSystemXmlApplicationContext
のコンストラクタには,文字列の配列を受け取るものもあるので,これを使ってBean定義のXMLとカスタマイズ用のXMLを一度に食べさせたあげましょう.
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext( new String[] {"factory.xml", "beans.xml"});
これでBeanFactory
カスタマイズ用のコードがなくなってすっきり.
おっと,BeanFactory
を後片付けするためのdestroySingletons()
もエラーになってやがる.そんなときはソースを(以下略).close()
にすればいいようです.
ということで,全部まとめると次のようになりました.
package study; import java.util.Iterator; import java.util.Map; import org.apache.commons.beanutils.BeanUtils; import org.springframework.context.support.FileSystemXmlApplicationContext; public class Main { public static void main(String args) { try { FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext( new String { "factory.xml", "beans.xml" }); String[] names = context.getBeanDefinitionNames(); for (int i = 0; i < names.length; ++i) { Object bean = context.getBean(names[i]); System.out.println(names[i] + " : " + bean); Map props = BeanUtils.describe(bean); for (Iterator it = props.entrySet().iterator(); it.hasNext();) { Map.Entry entry = (Map.Entry) it.next(); System.out.println("\t" + entry.getKey() + "=" + entry.getValue()); } } context.close(); } catch (Exception e) { e.printStackTrace(); } } }
たいして変わってないんですけどね.そうかぁ,BeanFactory
のカスタマイズは自分でコードを書く必要がなかったのかぁ.それを先に教えてくれよー.でもまぁ,日記のネタとしてはこれでよかったかな.水面下で行われていることもちょっとは分かった気がしますから.
これでApplicationContext
の付加機能を使う準備が出来ました.次回はその付加機能を使うべく,「3.10 Added functionality of the ApplicationContext」を学習します.
*1:コードより文章が多いと挫折しそうになります