ファイヤープロジェクト
BeanFactoryを使ってみる(Spring1.2RC2)
2005-05-07T00:25+09:00   matsu
BeanFactoryはSpringフレームワークの最も基本的な機能を提供するインタフェースらしいので,まずBeanFactoryを使用してみることから始めてみる.
二つのパッケージorg.springframework.beansとorg.springframework.contextは,Springで最も重要なパッケージである. この二つのパッケージではDI(Depencency Injection)を実現する. org.springframework.beans.factory.BeanFactoryは,応用的設定メカニズムを提供し,それによって設定ファイルからBeanにマッピングすることができる. BeanFactoryはさらに基本機能を提供する. org.springframework.context.ApplicationContextは,BeanFactoryのサブクラスで以下のような機能を追加的に持っている.
  • AOP機能
  • 国際化のためのメッセージリソースハンドリング
  • イベント伝播
  • ApplicationContextやオプションの親コンテキストを作成する宣言メカニズム
  • WebApplicationContextなどのアプリケーション層特有のコンテキスト
ApplicationContextはBeanFactoryの完全なスーパーセットなので,BeanFactoryに関する記述は,ApplicationContextにもあてはまる. 機能的にはBeanFactoryの方がApplicationContextより充実してり,かつApplicationContextはBeanFactoryのスーパーセットなので,どちらを使用すべきか迷ったらAppicationContextを使用すればよい. ただしメモリ量などの問題が予測されたり,AppicationContextの機能が明らかに不要な場合はBeanFactoryを選択する.
※ かつてはInversion of Controlと呼ばれていた. Mediatorパターンなどで,上位から結び付けるクラスを指定したりするのではなく,設定ファイルなどによって,(上位でコーディングすることなく)内側からクラス間を関連づけるパターン.
BeanFactoryは,設定ファイルからbeanを生成してくれる. したがって,アプリケーションはBeanFactoryに対してbeanを要求する作りになる. beanのインタフェースをきっておけば,具象クラスが何であるかとか,初期化値などはすべて設定ファイルに追い出すことができる. とにかくアプリケーションコードから今まで以上に具体的なものを追い出して,変更あるいは拡張に強い作りを目指すことができるようだ. BeanFactoryを使用するサンプルを作成してみた. 実行方法は以下.
$ tar zxvf HelloBeanFactory-0_01.tar.gz
$ ant init
$ ant preparelib
$ ant run
上記preparelibにて依存しているjarも含めたSpringをhttpにてダウンロードする. HTTPプロキシには対応していない. このサンプルを作成する際のポイントは以下であった.
  1. 設定ファイルを作成する.
  2. beanクラスを作成する.
  3. サンプルドライバにてBeanFactoryを生成する.
  4. サンプルドライバにてBeanFactoryからbeanを取得する.
以下順に解説していく.
設定ファイルではbeanの設定,定義を記述する. サンプルの設定ファイルを以下にしめす.
この設定ファイルではいろいろな設定が可能だが,今回は最も簡単と思われる構成にした. ポイントを以下に示す.
ルート要素beans
設定ファイルはXMLファイルで,ルート要素はbeansである.
bean設定要素bean
beans要素の子要素として各beanの設定にあたる要素beanを記述する.
beanの属性class
beanクラスまたはbeanクラスを生成するFactoryクラスのFQCN. このサンプルではbeanクラスを指定した. すなわちSpringはbeanクラス自身のコンストラクタでbeanクラスをインスタンス化する.
beanの属性id,name
属性idはXMLのIDである. これにそぐわないものを設定したい場合は属性nameを使用する. いずれにせよプログラムからBeanFactoryを介してインスタンスを取得するのに使用するので一意でなくてはならない.
beanの初期化
要素beanの子要素propertyにてbeanの初期化指定ができる. 要素propertyの属性nameがフィールド名で,beanはこのフィールド名に基づいたsetterとgetterを持たなければならない. 初期化値にはbeanのネストなどいろいろ指定可能だが,今回はもっとも簡単な,要素valueによる指定値による初期化とした.
より具体的には以下の条件を満たすクラスを作成する.
  • 引数のないpublicなコンストラクタを持つ
  • 全フィールドにsetterとgetterを持つ. メソッド名はsetXxx,getXxxというパターンにする.
サンプルでは以下のようになる.
toStringメソッドは動作確認用(ログ出力用)である.
サンプルではBeanFactoryの具象クラスとしてXmlBeanFactoryを使用した.
XmlBeanFactoryはbean設定ファイルを表すResourceオブジェクトを引数にとる. Resourceの具象クラスには以下がある.
ClassPathResource
ClassLoaderにfindResourceしてbean設定ファイルを得る. 今回試した場合にはうまく見付けられなかった. さらにjarファイルからは見付けられないらしい.
FileSystemResource
指定したファイルのパスからbean設定ファイルを得る. ファイルパスが変動するような場合,設定や指定が面倒である.
InputStreamResource
bean設定ファイルを何らかの方法でInputStreamとして得る.
UrlResource
URLからbean設定ファイルを得る.
ServletContextResource
サーブレットコンテキストとパスからbean設定ファイルを得る. 試していない.
ClassPathResourceが楽そうだったが,うまく見付けられなかった上に,jarからは見付けられないようなので,ClassからgetResourceしてUrlResourceする方法とした.
URL url = HelloBeanFactory.class.getResource("beans.xml");
Resource res = new UrlResource(url);
BeanFactory factory = new XmlBeanFactory(res);
コメントアウトしているが,FileSystemResource,InputStreamResourceも動作確認できた(前者はしかるべき場所にbeans.xmlを置く必要がある). BeanFactoryが取得できれば,あとはidやnameによって取得するだけである.
HelloBean helloBeanById = (HelloBean)factory.getBean("helloid");
サンプルのログから指定した値でうまく初期化できていること,beanがsingletonであることが分かる.
2005-05-07 00:20:00,895 INFO  [main] xml.XmlBeanDefinitionReader:132
  - Loading XML bean definitions from URL
  [jar:file:/home/matsu/programing/java/spring/dicontainer1/springsample.jar!
  /org/fireproject/springsample/beans.xml]
2005-05-07 00:20:00,984 INFO  [main] springsample.HelloBeanFactory:32
   - ====== get HelloBean by id
2005-05-07 00:20:00,990 INFO  [main] support.AbstractBeanFactory:219
   - Creating shared instance of singleton bean 'helloid'
2005-05-07 00:20:01,122 INFO  [main] springsample.HelloBeanFactory:34
   - org.fireproject.springsample.HelloBean[messge=Hello Bean!!!!;value=1;]
2005-05-07 00:20:01,123 INFO  [main] springsample.HelloBeanFactory:40
   - ====== get HelloBean by name
2005-05-07 00:20:01,123 INFO  [main] springsample.HelloBeanFactory:42
   - org.fireproject.springsample.HelloBean[messge=Hello Bean!!!!!!!!!;value=10;]
2005-05-07 00:20:01,124 INFO  [main] springsample.HelloBeanFactory:45
   - helloBeanById == helloBeanByName ? true
matsu(C)
Since 2002
Mail to matsu