BeanFactoryPostProcessorとPropertyPlaceholderConfigurer(Spring1.2.1)
BeanFactoryPostProcessorは,BeanFactoryをインスタンス化した後に,そのインスタンスを引数にとり,何らかの処理をするものである.アプリケーションの起動後の初期化パターンとして使えることがあると思う.BeanFactoryPostProcessorの一つ,PropertyPlaceholderConfigurerは,設定ファイルであるbeans.xmlでの設定値を更に外部プロパティファイルへと移動することが可能な機能を持つらしいので,BeanFacotryPostProcesssorの挙動確認を兼ねて試してみた.
BeanFactoryPostProcessorは,インタフェースであり,以下のメソッドを宣言している.
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)ここで,アプリケーションにBeanFactoryPostProcessorを組み込むというのは,以下の作業を指す.
- BeanFactoryPostProcessor具象クラスの作成. あるいはSpringFrameworkにある上記具象クラスの選定. 本頁のサンプルでは,あるいはSpringFrameworkにあるPropertyPlaceholderConfigurerを使用する. この詳細は後述.
- BeanFactoryクラスの生成.
- 上で作成あるいは生成したBeanFactoryPostProcessorクラスの生成.
- BeanFactoryPostProcessorのpostProcessBeanFactoryを呼び出す. 引数は先に生成したBeanFactoryオブジェクトである.
PropertyPlaceholderConfigurerは,beans.xmlに設定シンボルを記述し,そのシンボルに別プロパティファイルのプロパティ値を埋め込む.
以下はPropertyPlaceholderConfigurerを使用する本頁のサンプルのbeans.xmlである.
${...}で記述された部分は,今までならそのまま文字列としてbeanにsetされていたが,PropertyPlaceholderConfigurerの働きにより,プロパティファイルの値に置き換えられる.
例えば,プロパティファイルに
sampleBean.value1=HOGEとあれば,beans.xmlの
<property name="value1"><value>${sampleBean.value1}</value></property>
という記述は
<property name="value1"><value>HOGE</value></property>と置き換えられて処理される. この置き換えのタイミングは,PropertyPlaceholderConfigurer#postProcessBeanFactory呼び出し時である.
以下にサンプルのドライバクラスを示す.
BeanPostProcessorのハードコードによる生成と使用は,getBeanFactoryメソッドにて行っている.
これは,各メソッドの呼び出しタイミングを知るためにログ出力をしている程度で,それ以外は直接PropertyPlaceholderConfigurerを使用するのと変わらない.
ApplicationContextは,beans.xmlにBeanPostProcessorの具象クラスであるSampleBeanFactoryPostProcessorが記述されているので,これを自動検知し,インスタンス化し,postProcessBeanFactoryを実行する.
ハードコードする方法と,ApplicationContextを使用する方法では,行数は1行しか違わないが,プロパティファイルを外部化している点はもちろん,BeanFactoryPostProcessorの生成,呼び出しそのものを設定ファイル化している点で,ApplicationContextを使用した方法の方がより柔軟で実装も楽ある.
最後にサンプルを実行した際のログを示す.
まずハードコード版.
XmlBeanFactory factory = new XmlBeanFactory(res);
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("./conf/springsample.conf"));
cfg.postProcessBeanFactory(factory);
BeanFactoryを生成し,BeanFactoryPostProcessorの具象クラスであるPropertyPlaceholderConfigurerをインスタンス化,設定しpostProcessBeanFactoryを呼び出している.
ApplicationContextを使用すると,これと同様の処理は以下となる.
XmlBeanFactory factory = new XmlBeanFactory(res); GenericApplicationContext ctx = new GenericApplicationContext(factory); ctx.refresh();今回は,beans.xmlにはSampleBeanFactoryPostProcessorを記述した.
$> java -jar springsample.jar springsample.HelloBeanFactory:52 - getBeanFactory start xml.XmlBeanDefinitionReader:132 - Loading XML bean definitions from URL [jar:file:/home/matsu/springsample.jar !/org/fireproject/springsample/beans.xml] config.PropertyResourceConfigurer:154 - Loading properties from file [/home/matsu/./conf/springsample.conf] support.AbstractBeanFactory:219 - Creating shared instance of singleton bean 'sampleBean' springsample.SampleBean:12 - setValue1: param = HOGE springsample.SampleBean:23 - setValue2: param = FUGA springsample.SampleBean:34 - setValue3: param = FOO springsample.SampleBean:45 - setValue4: param = BAR springsample.SampleBean:56 - setValue5: param = 100 springsample.HelloBeanFactory:41 - org.fireproject.springsample.SampleBean [valu1 = HOGE / valu2 = FUGA / valu3 = FOO / valu4 = BAR / valu5 = 100]次にApplicationContext版.
$> java -jar springsample.jar useApplicationContext springsample.HelloBeanFactory:76 - getApplicationContext start xml.XmlBeanDefinitionReader:132 - Loading XML bean definitions from URL [jar:file:/home/matsu/springsample.jar !/org/fireproject/springsample/beans.xml] support.AbstractApplicationContext:289 - 2 beans defined in application context [org.springframework.context.support.GenericApplicationContext;hashCode=20233936] support.AbstractBeanFactory:219 - Creating shared instance of singleton bean 'sampleBeanFactoryPostProcessor' springsample.SampleBeanFactoryPostProcessor:15 - setLocation of org.fireproject.springsample.SampleBeanFactoryPostProcessor springsample.SampleBeanFactoryPostProcessor:20 - postProcessBeanFactory of org.fireproject.springsample.SampleBeanFactoryPostProcessor springsample.SampleBeanFactoryPostProcessor:21 - beanFactory = org.springframework.beans.factory.xml.XmlBeanFactory config.PropertyResourceConfigurer:154 - Loading properties from file [/home/matsu/./conf/springsample2.conf] ...省略... support.DefaultListableBeanFactory:262 - Pre-instantiating singletons in factory [org.springframework.beans.factory.xml.XmlBeanFactory defining beans [sampleBean,sampleBeanFactoryPostProcessor]; root of BeanFactory hierarchy] support.AbstractBeanFactory:219 - Creating shared instance of singleton bean 'sampleBean' springsample.SampleBean:12 - setValue1: param = HOGE2 springsample.SampleBean:23 - setValue2: param = FUGA2 springsample.SampleBean:34 - setValue3: param = FOO2 springsample.SampleBean:45 - setValue4: param = BAR2 springsample.SampleBean:56 - setValue5: param = 200 springsample.HelloBeanFactory:41 - org.fireproject.springsample.SampleBean [valu1 = HOGE2 / valu2 = FUGA2 / valu3 = FOO2 / valu4 = BAR2 / valu5 = 200]

