めざましテレビ
今日の早耳ムスメは石田香奈ちゃん,お題は「この冬食べたい!! 人気の鍋 第2弾」.
...
なんか,香奈ちゃん画面に映らないんですけど.全く映らないわけじゃないけど少ないんですけど.紗世ちゃんの時にこれだったら抗議の電話かけちゃうところですよ.
ともあれ (JW),それ以上書くこともなく...
今朝は石田香奈が「絶対食べたい!!あったか鍋」を紹介。彼女の食レポも回を重ねるごとに上手になり、特にコメントの部分は美味く言えてると思うのですが、食べるときの表情だけは天使の食レポーター臼田あさ美に敵いません。
おぉっ,「天使の食レポーター」!! (^^;
変なところに反応してスミマセン,でもナイスな表現ですね.食レポのあさ美ちゃんはまさに天使ですもんねぇ〜.そろそろ明日辺り登場でしょうか? でないと,まこたんがいじけちゃうもんね!?
Lakers 93 - 108 Supersonics
(ToT)
惨敗...
BeanFactory の階層構造
謎めきすぎて自分が書いていいものか分かりませんが,ちょっと書いてみるテスト.でも,Spring 入門記を終えて長いので信憑性低いですから!! 残念!!!!
Spring のコンテナである BeanFactory
の階層といった場合,次の三つの階層があると思います.
interface
の階層構造class
の階層構造- インスタンスの階層構造
おそらく多くの人が興味あるのは最後のやつだと思うのですが,一応順番に一つずつ.
interface
の階層構造
S2 と違って,Spring の場合たくさんの interface
が用意されています.Java の interface
は多重継承が出来るので,単なる階層構造ではないのですが,一応主なものを書き出してみると...
BeanFactory
ListableBeanFactory
HierarchicalBeanFactory
ConfigurableBeanFactory
ConfigurableListableBeanFactory
ConfigurableListableBeanFactory
は ListableBeanFactory
も extends
しています.
それぞれの役割はほぼ見たまんま.
ここで注意したいのは HierarchicalBeanFactory
.階層化することの出来る BeanFacotry
の interface
です.でも,getParentBeanFactory()
が定義されているだけなんですけどね.(^^;
Spring にはもうひとつ,ApplicationContext
というコンテナもあって,こちらは次のようになっています.
ApplicationContext
ConfigurableApplicationContext
ApplicationContext
は,ListableBeanFactory
と HierarchicalBeanFactory
を extends
していますが,ConfigurableApplicationContext
は ConfigurableBeanFactory
を extends
していません.なんか微妙.
という具合にいろいろ細分化されているのですが,実際にはほとんど意味がありません.なぜなら,実装クラスはそこまで細かく用意されているわけではないからです.
class
の階層構造
実装クラスもいろいろ用意されています.
ますは BeanFactory
の実装クラス.
AbstractBeanFactory
AbstractAutowireCapableBeanFactory
DefaultListableBeanFactory
StaticListableBeanFactory
XmlBeanFactory
AbstractBeanFactory
は,ConfigurableBeanFactory
を implements
しています.つまり,BeanFactory
だけ,あるいは HierarchicalBeanFactory
だけを implements
した実装は用意されていません.
ApplicationContext
の実装クラスは次のようになっています.
AbstractApplicationContext
AbstractRefreshableApplicationContext
AbstractXmlApplicationContext
ClassPathXmlApplicationContext
FileSystemXmlApplicationContext
GenericApplicationContext
StaticApplicationContext
AbstractApplicationContext
は,ConfigurableApplicationContext
を implements
しています.つまり,ApplicationContext
だけを implements
した実装は用意されていません.
興味深いのは,XML による定義ファイルを扱うためにコンテナのサブクラスが用意されていることです.しかも ApplicationContext
ではクラスパスから XML を見つけるのか,ファイルシステムから見つけるのかが違うだけのものまで.一方 S2 では,コンテナの実装クラスは一つしか用意されていません.それでいながら,XML による定義ファイルだけでなく,Groovy による定義ファイルを使うことも出来ます.これは,コンテナではなくコンテナビルダーを複数使い分けることで実現されています.コンテナそのものと,コンテナをセットアップすることを分けているわけです.Spring は interface
や class
を細かく分割している割に,責務の分け方はイマイチだと思います.
インスタンスの階層構造
さて,おそらく本命であろうインスタンスの階層構造ですが,実はよく分かっていません (苦笑).入門記でも結局扱ってないような.だってリファレンスにほとんど情報がありませんから!! 残念!!!!
そんなわけで (どんなわけで?),以下に書いてあることは信憑性 0 くらいということで.(^^;
まず,Spring におけるコンテナの階層構造は,前述の HierarchicalBeanFactory
によって定義されます.でも,これはさっきも書いたように親のコンテナを取得することが出来る,というだけです.実際には HierarchicalBeanFactory
でない BeanFactory
の実装は見あたらないので,AbstractBeanFactory
を調べればよいことになります.すると...
興味深いことが分かります.AbstractBeanFactory
は,親コンテナへの参照は保持していますが,親は子のコンテナを保持していないのです!! そして,BeanFactory#getBean(String)
の JavaDoc にも,興味深い記述があります.
This method delegates to the parent factory if the bean cannot be found in this factory instance.
もし,メソッドが呼び出されたコンテナに該当の Bean が存在しなければ,親のコンテナを探しに行くとだけ書かれています.つまり,子のコンテナからは探してくれないのですね.
確認してみましょう.
まずは単純な Bean を用意.
package hoge; public class Model { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
そして定義ファイル.今回は 3 つも用意.
まずは定義ファイルをひとまとめに扱う SingletonBeanFactoryLocator
が読み込むための beanRefFactory.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="foo" lazy-init="true" class="org.springframework.context.support.ClassPathXmlApplicationContext"> <constructor-arg> <value>foo.xml</value> </constructor-arg> </bean> <bean id="bar" lazy-init="true" class="org.springframework.context.support.ClassPathXmlApplicationContext"> <constructor-arg> <list> <value>bar.xml</value> </list> </constructor-arg> <constructor-arg> <ref bean="foo"/> </constructor-arg> </bean> </beans>
ここでは,2 つのコンテナを定義しています.親 (foo) と子 (bar) です.
そんなわけで (どんなわけで?),親の定義ファイル,foo.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="yuri" class="hoge.Model"> <property name="name"><value>Yuri Ebihara</value></property> </bean> </beans>
そして子の定義ファイル bar.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="moe" class="hoge.Model"> <property name="name"><value>Moe Oshikiri</value></property> </bean> </beans>
そして実行用のクラス.
package hoge; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.access.BeanFactoryLocator; import org.springframework.beans.factory.access.SingletonBeanFactoryLocator; public class Main { public static void main(String[] args) { try { BeanFactoryLocator locator = SingletonBeanFactoryLocator.getInstance(); BeanFactory foo = locator.useBeanFactory("foo").getFactory(); BeanFactory bar = locator.useBeanFactory("bar").getFactory(); Model yuri = (Model) foo.getBean("yuri"); System.out.println(yuri.getName()); Model moe = (Model) bar.getBean("moe"); System.out.println(moe.getName()); } catch (Exception e) { e.printStackTrace(); } } }
まずは親と子それぞれのコンテナから,自身が持つ Bean を取り出しています.
こいつを実行!!
Yuri Ebihara Moe Oshikiri
ふむ.
次に,二つの Bean (yuri と moe) をともに bar
から取得するようにして実行!!
Yuri Ebihara Moe Oshikiri
bar
には yuri はいないはずですが,親である foo
から探してきてくれました.
次に,二つの Bean を foo
から取得するようにして実行!!
Yuri Ebihara org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'moe' is defined: org.springframework.beans.factory.support.DefaultListableBeanFactory defining beans [yuri]; root of BeanFactory hierarchy
ぐはぁっ (お約束).
もえちゃんを見つけてくれませんでした.やはり,子のコンテナから Bean を探したりはしないようです.
これで,Spring のコンテナは自分にない Bean は親へ探しに行くだけで,子から探すことはないということが確認できました.これは見事なまでに S2 と対照的ですね.S2 では,コンテナは自分にないコンポーネントは子のコンテナから探してくれますが,親からは探してくれません.ですよね?
なんという方針の違い.(^^;
おそらく,Spring ではデフォルトのコンポーネントを上の方のコンテナで定義して,下の方のコンテナでは必要に応じて別のコンポーネントを登録 (オーバーライド) する,という使い方を想定しているのでしょうね.一方で S2 は標準的なコンポーネントは必要に応じてインクルードすることで,子のコンテナに持たせることになります.
もうひとつ,Spring では,定義ファイルの分割はコンテナの階層構造とは別ものであることに注意するべきかもしれません.
実際,先の例での foo.xml
と bar.xml
を一つのコンテナに読み込ませることが出来ます.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="foo" lazy-init="true" class="org.springframework.context.support.ClassPathXmlApplicationContext"> <constructor-arg> <list> <value>foo.xml</value> <value>bar.xml</value> </list> </constructor-arg> </bean> </beans>
一方,S2 では基本的に一つの定義ファイルに一つのコンテナが対応することになると思います.分割された定義ファイルを扱うにはインクルードを使うことになり,すると子のコンテナが作られます.
このような違いがあるため,Spring では S2 に比べて子のコンテナからコンポーネントを検索する必要があまりないのかもしれません.
そのせいか,Spring ではコンテナの階層構造を一つのファイルで集中管理する形になっています.もしかしたら beanRefFactory.xml
の中でさらに BeanFactoryLocator
を使うのもありなのかもしれませんが,基本的にBeanFactoryLocator
はシングルトンみたいなものなので,そんなことはしないはず.一方 S2 ではコンテナの階層構造は個々の dicon ファイルに記述されることになります.これまた大きな違い.
そこそこの規模ならコンテナ (というより定義ファイル) 間の依存関係を一つのファイルで確認できるのは悪くない気もしますが,大きくなってきたら破綻しそう.S2 の場合はそれぞれの定義ファイルが必要なものをインクルードしていて自己記述的かつ完結しているので,大規模になっても困ることは少なそうです.
コンテナの階層構造とその管理,そしてコンポーネントが見える範囲というのは,定義ファイルの表現力以上に Spring と S2 の大きな違いかもしれませんね.
S2Axis serviceType と allowedMethods
ちょっとずつでも実装を進めようということで,今日は serviceType と allowedMethods を実装しました.
serviceType は Axis の WSDD で
<service name="MyService" provider="java:RPC"> <parameter name="className" value="foo.Foo"/>
と書いた場合の,className
に該当します.
WSDD に記述した className
は,サービスの実装クラスを示すと同時に,?wsdl
によって WSDL を生成する元ネタになります (別途 WSDL ファイルを指定しなかった場合).
S2Axis (っていうか S2) の場合,サービスの実装クラスは dicon の <component>
要素に記述されるため,別途実装クラスを指定する必要はありませんが,WSDL ファイルを生成する元ネタは実装クラスではなくて Java interface
にできるとうれしかったりするはず.
そんなわけで (どんなわけで?),S2 が解釈する <compoent>
要素の class
属性とは別に,<meta>
要素内に serviceType
プロパティを指定できるようにしました.なんで名前が className
ではないかというと,このプロパティは String
ではなくて Class
型なのです.なので,className
は変.でも class
だと Object#getClass()
とバッティングしてそんなプロパティ作れないのと,class
よりむしろ interface
を指定するだろうということで,serviceType
にしましたとさ.
そして allowedMethods
は WSDD で指定できるものと全く同じです.もっと凝ったものにしようかと思っていたのですが,interface
にメソッドを書いておきながらそのメソッドを Web サービスとして公開しないのは使い方がおかしくないか? という気のせいがしたので,あまり活用すべきものでもないと判断して Axis が提供する機能そのままという事にしておきます.
ということで,現状 S2Axis を使う場合の app.dicon はこんな感じになってます.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN" "http://www.seasar.org/dtd/components21.dtd"> <components> <include path="s2axis.dicon"/> <component name="Foo" class="org.seasar.axis.examples.foo.FooImpl"> <property name="fullName"> <component class="org.seasar.axis.examples.foo.FullName"> <property name="firstName">"Yuri"</property> <property name="lastName">"Ebihara"</property> </component> </property> <meta name="s2axis:rpc-service"> <component class="org.seasar.axis.server.ServiceDef"> <property name="serviceType">@org.seasar.axis.examples.foo.Foo@class</property> <property name="allowedMethods">"getFullName"</property> <initMethod name="addBeanMappingDef"> <arg> <component class="org.seasar.axis.server.BeanMappingDef"> <property name="type">@org.seasar.axis.examples.foo.FullName@class</property> </component> </arg> </initMethod> </component> </meta> </component> </components>
以前書いた構想とは全然違ってます.(^^;
<meta>
の name
属性は Kijimuna に補完してもらえないので,<meta>
を使いまくるのはやめて,その中に <component>
要素を置くことにしました.
<meta name="s2axis:rpc-service">
のついたコンポーネントを探して Axis に登録するコンポーネントは s2axis.dicon
の中に定義されています.
こうやって見ると,BeanMapping/TypeMapping の定義は煩雑でうんざりしそう... やっぱり BeanMapping は自動で登録したいですね.頑張ろ.
Web サービス 本
Amazon から届きました.
Building Web Services with Java: Making Sense of XML, SOAP, WSDL, and UDDI (Developer's Library)
- 作者: Steve Davis, Doug Simeonov, Simeon Daniels, Glen Brittenham, Peter Nakamura, Yuichi Fremantle, Paul Koenig, Dieter Zentner, Claudia Graham
- 出版社/メーカー: Sams
- 発売日: 2004/06/28
- メディア: ペーパーバック
- クリック: 1回
- この商品を含むブログ (1件) を見る
- 作者: Inderjeet Singh,Sean Brydon,Greg Murray,Vijay Ramachandran,Thierry Violleau,Beth Stearns
- 出版社/メーカー: Prentice Hall
- 発売日: 2004/06/19
- メディア: ペーパーバック
- クリック: 2回
- この商品を含むブログ (1件) を見る
(^^;
後者は持ち歩けるかな.約 400 ページ.
特に WSDL が全然分かっていないので,自分で一から書けるくらいになりたいなと思ってみたり.思っただけですが.
っていうか,S2Axis やっていながら今更 Web サービス入門しなきゃいけないってのは世間的にどうなんだろうか?
(^^;
ってういか,またしても積ん読を増やすだけのような気のせいがするのはいかがなものかと (苦笑).