めざましテレビ

今日の早耳ムスメ石田香奈ちゃん,お題は「この冬食べたい!! 人気の 第2弾」.
...
なんか,香奈ちゃん画面に映らないんですけど.全く映らないわけじゃないけど少ないんですけど.紗世ちゃんの時にこれだったら抗議の電話かけちゃうところですよ.
ともあれ (JW),それ以上書くこともなく...

今朝は石田香奈が「絶対食べたい!!あったか鍋」を紹介。彼女の食レポも回を重ねるごとに上手になり、特にコメントの部分は美味く言えてると思うのですが、食べるときの表情だけは天使の食レポーター臼田あさ美に敵いません。

おぉっ,「天使の食レポーター」!! (^^;
変なところに反応してスミマセン,でもナイスな表現ですね.食レポのあさ美ちゃんはまさに天使ですもんねぇ〜.そろそろ明日辺り登場でしょうか? でないと,まこたんがいじけちゃうもんね!?

BeanFactory の階層構造

謎めきすぎて自分が書いていいものか分かりませんが,ちょっと書いてみるテスト.でも,Spring 入門記を終えて長いので信憑性低いですから!! 残念!!!!


Spring のコンテナである BeanFactory の階層といった場合,次の三つの階層があると思います.

おそらく多くの人が興味あるのは最後のやつだと思うのですが,一応順番に一つずつ.


interface の階層構造
S2 と違って,Spring の場合たくさんの interface が用意されています.Javainterface は多重継承が出来るので,単なる階層構造ではないのですが,一応主なものを書き出してみると...

  • BeanFactory
    • ListableBeanFactory
    • HierarchicalBeanFactory
      • ConfigurableBeanFactory
        • ConfigurableListableBeanFactory

ConfigurableListableBeanFactoryListableBeanFactoryextends しています.
それぞれの役割はほぼ見たまんま.
ここで注意したいのは HierarchicalBeanFactory.階層化することの出来る BeanFacotryinterface です.でも,getParentBeanFactory() が定義されているだけなんですけどね.(^^;


Spring にはもうひとつ,ApplicationContext というコンテナもあって,こちらは次のようになっています.

  • ApplicationContext
    • ConfigurableApplicationContext

ApplicationContext は,ListableBeanFactoryHierarchicalBeanFactoryextends していますが,ConfigurableApplicationContextConfigurableBeanFactoryextends していません.なんか微妙.
という具合にいろいろ細分化されているのですが,実際にはほとんど意味がありません.なぜなら,実装クラスはそこまで細かく用意されているわけではないからです.


class の階層構造
実装クラスもいろいろ用意されています.
ますは BeanFactory の実装クラス.

  • AbstractBeanFactory
    • AbstractAutowireCapableBeanFactory
      • DefaultListableBeanFactory
        • StaticListableBeanFactory
        • XmlBeanFactory

AbstractBeanFactory は,ConfigurableBeanFactoryimplements しています.つまり,BeanFactory だけ,あるいは HierarchicalBeanFactory だけを implements した実装は用意されていません.


ApplicationContext の実装クラスは次のようになっています.

  • AbstractApplicationContext
    • AbstractRefreshableApplicationContext
      • AbstractXmlApplicationContext
        • ClassPathXmlApplicationContext
        • FileSystemXmlApplicationContext
    • GenericApplicationContext
      • StaticApplicationContext

AbstractApplicationContext は,ConfigurableApplicationContextimplements しています.つまり,ApplicationContext だけを implements した実装は用意されていません.
興味深いのは,XML による定義ファイルを扱うためにコンテナのサブクラスが用意されていることです.しかも ApplicationContext ではクラスパスから XML を見つけるのか,ファイルシステムから見つけるのかが違うだけのものまで.一方 S2 では,コンテナの実装クラスは一つしか用意されていません.それでいながら,XML による定義ファイルだけでなく,Groovy による定義ファイルを使うことも出来ます.これは,コンテナではなくコンテナビルダーを複数使い分けることで実現されています.コンテナそのものと,コンテナをセットアップすることを分けているわけです.Spring は interfaceclass を細かく分割している割に,責務の分け方はイマイチだと思います.


インスタンスの階層構造
さて,おそらく本命であろうインスタンスの階層構造ですが,実はよく分かっていません (苦笑).入門記でも結局扱ってないような.だってリファレンスにほとんど情報がありませんから!! 残念!!!!
そんなわけで (どんなわけで?),以下に書いてあることは信憑性 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.xmlbar.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)

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件) を見る
Designing Web Services with the J2EE(TM) 1.4 Platform: JAX-RPC, SOAP, and  XML Technologies (Java Series)

Designing Web Services with the J2EE(TM) 1.4 Platform: JAX-RPC, SOAP, and XML Technologies (Java Series)

  • 作者: Inderjeet Singh,Sean Brydon,Greg Murray,Vijay Ramachandran,Thierry Violleau,Beth Stearns
  • 出版社/メーカー: Prentice Hall
  • 発売日: 2004/06/19
  • メディア: ペーパーバック
  • クリック: 2回
  • この商品を含むブログ (1件) を見る
前者は厚いです.約 800 ページ... 自分の鞄には入らないので持ち歩けません.流行のぶった切り? おいらには無理.(^^;
後者は持ち歩けるかな.約 400 ページ.
特に WSDL が全然分かっていないので,自分で一から書けるくらいになりたいなと思ってみたり.思っただけですが.
っていうか,S2Axis やっていながら今更 Web サービス入門しなきゃいけないってのは世間的にどうなんだろうか? (^^;
ってういか,またしても積ん読を増やすだけのような気のせいがするのはいかがなものかと (苦笑).

出演予定 TV 番組

この近辺 (どこ?) で話題のモデルが出演するテレビ番組を分かるだけ掲載します.
新規分は赤字で (レギュラー除く).直近分は太字で.

山田優
12/16 (木) 23:40〜00:10 NTV 「Xmas なんて大嫌い」
蛯原友里
12/17 (金) 23:00〜23:30 TBS 「恋するハニカミ!」
12/19 (日) 02:40〜04:30 ANB 「特命係長・只野仁 (再)」
12/22 (水) 21:00〜23:09 ANB 「特命係長・只野仁リターンズ」

CanCam 01 月号 エビちゃんベストセレクション 21

CamCam2005年01月号の蛯原友里ちゃん

CanCam から,お気に入りの蛯原友里ちゃんを紹介しようというこのコーナー.
今日もゼイヴェルという通販会社 (?) とのタイアップで「恋を呼び込む激モテ BOOK」という綴じ込み付録の友里ちゃん.
いつもは顔アップですが,今日はバストアップ気味で.本当は全身のカットなので,そのままスキャンしようかと思っていたら中途半端な大きさにしてしまいました.無念だ.
なぜ全身のカットのままスキャンしたかったかというと,この友里ちゃん,犬 (くぅーちゃんタイプ) を連れてるのです!! おいらも一緒に散歩したいゾ!!!!
そんなわけで (どんなわけで?),やっぱり CanCam 買うしか!!