Spring Framework 入門記 BeanWrapper
今回は「Chapter 4. PropertyEditors, data binding, validation and the BeanWrapper」です.3章と比べると分量が少ないので,あっという間に終われそうです.というかですね,このタイトルから分かるとおり,この章は3章からこぼれたと思われる4つのネタを解説しているだけという感じがするんですね.しかも,そのうちのPropertyEditor
はすでに「Beanその9 PropertyEditorだよ」で学習済み,そしてdata bindingはというと,
4.2. Binding data using the DataBinder
The DataBinder builds on top of the BeanWrapper.
これだけですよ,これだけ.(^^;
validationにいたっては,導入部でそういうものがあると紹介されている程度.
どうしろっていうんでしょうねぇ? いやその,ソースを見れるのがオープンソースのいいところではあるのですが,あうあう.
というわけで(謎),残りはBeanWrapper
だけとなりました.えっ? それでいいのかって? いいんです!(死語).
そんなわけでBeanWrapperですが,これはBeanのプロパティに式言語(EL)のような文字列でアクセスするユーティリティ的なものですね.ドキュメントによると,
name
- Beanの
name
というプロパティにアクセスします.getName()
やsetName()
に相当します. account.name
- Beanの
account
というプロパテが参照するBeanのname
というプロパティにアクセスします.getAccount().getName()
などに相当します. account[2]
- Beanの
account
という配列またはList
などのプロパティの3番目の要素にアクセスします.getAccount()[2]
またはgetAccount().get(2)
などに相当します.
ということで,うまく使えればいい感じ.
使い方も簡単で,操作対象のBeanをBeanWrapperImpl
でラップして,getPropertyValue(String)
またはsetPropertyValue(String, Object)
などのメソッドを呼べばいいだけのようです.
さて,これをどう使いましょうか.どうせなら,上記の式言語もどきをBean定義XMLの中で使えればいいですね.XML中に定義されたBeanのプロパティをたどった結果を好きなBeanのプロパティに設定できたりとか.うんうん.
そんな場合に使えるのがFactoryBean
です.BeanFactory
じゃありませんよ,「Beanその10 FactoryBean
」で学習した,それ自身がファクトリであるBeanというヤツです.そう,こいつは自分もBeanとして定義ファイルに記述されるものの,コンテナが扱うのはこいつが返したオブジェクトでした.そうです,そこで式言語もどきを評価した結果を返してあげれば... うん,その方が素敵(キラッ).
よし,早速作ってみましょう.
式言語もどきとそれを適用する対象(ターゲット)のオブジェクトをプロパティにすればいいはずです.その他FactoryBean
に必要なものを含めて,次のようになりました.
package study; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.factory.FactoryBean; public class PropertyValueFactoryBean implements FactoryBean { private Class objectType; private boolean singleton; private Object target; private String expression; public Object getObject() { BeanWrapper wrapper = new BeanWrapperImpl(target); return wrapper.getPropertyValue(expression); } //以下はフィールドのgetterおよびsetter public Class getObjectType() { return objectType; } public void setObjectType(Class objectType) { this.objectType = objectType; } public boolean isSingleton() { return singleton; } public void setSingleton(boolean singleton) { this.singleton = singleton; } public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } public String getExpression() { return expression; } public void setExpression(String expression) { this.expression = expression; } }
ちょっとプロパティの数が多いためコードが長く見えますが,中身は無いも同然ですね.
さて,実験用にいくつかしょぼいクラスを作ります.
package study; public class ObjectHolder { private Object object; public Object getObject() { return object; } public void setObject(Object object) { this.object = object; } }
package study; import java.util.Collection; public class CollectionHolder { private Collection collection; public Collection getCollection() { return collection; } public void setCollection(Collection collection) { this.collection = collection; } }
package study; public class StringHolder { private String string; public String getString() { return string; } public void setString(String string) { this.string = string; } }
それぞれ,Object
,Collection
,String
のプロパティを1つ持つだけのまったく役に立ちそうも無い代物です.
で,こいつらを使う定義ファイルを用意します.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean name="root" class="study.ObjectHolder"> <property name="object"> <bean class="study.CollectionHolder"> <property name="collection"> <list> <bean class="study.StringHolder"> <property name="string"><value>Spring is comming.</value></property> </bean> <bean class="study.StringHolder"> <property name="string"><value>Spring is here.</value></property> </bean> </list> </property> </bean> </property> </bean> <bean name="foo" class="study.StringHolder"> <property name="string"> <bean class="study.PropertyValueFactoryBean"> <property name="objectType"><value>java.lang.String</value></property> <property name="target"><ref bean="root"/></property> <property name="expression"><value>object.collection[1].string</value></property> </bean> </property> </bean> </beans>
前半で定義しているroot
というBean以下は,式言語もどきでアクセスする対象となるBeanのツリーです.
後半で定義しているfoo
では,そのプロパティの値を設定するために,PropertyValueFactoryBean
を使用しています.ターゲットはroot
です.
で,これを「Contextその1 ApplicationContext
」のMain
クラスで実行すると...
foo : study.StringHolder@787d6a string=Spring is here. class=class study.StringHolder
という結果になりました.ちゃんとexpression
プロパティの値を評価した結果が入っています.やったね.
これがそんなに便利という感じはしませんが,困ったときには使えるかもしれません.どう困ったときに使えるかは分かりませんが.
さぁ,これで4章も終わりにしてしまおう.いよいよ次は「Chapter 5. Spring AOP: Aspect Oriented Programming with Spring」に進みます.楽しみ(^o^)