2012年4月30日月曜日

seasar2 コンポーネント自動登録

seasar2のコンポーネント自動登録の基本

初めて使ったときに悩んだのでメモ。

コンポーネントの自動登録を理解するために、最もシンプルにしたプロジェクトでサンプルを提示します。

1.自動登録を使用しない場合(プロジェクト名:ComponentManualRegisterSample1)

(1)パッケージ構成


(2)各ソース

ClassAImpl.java
package org.yama.study.pk1;

public class ClassAImpl {
public void say() {
System.out.println("Hello Manual Registar!");
}
}

Driver.java
package org.yama.study.pk1;

import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;

public class Driver {
public static void main(String[] args) {
SingletonS2ContainerFactory.init();
S2Container container = SingletonS2ContainerFactory.getContainer();
ClassAImpl ca = (ClassAImpl) container.getComponent("classA");
ca.say();
  }
}

app.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
"http://www.seasar.org/dtd/components24.dtd">
<components>
    <component name="classA" class="org.yama.study.pk1.ClassAImpl">
    </component>
</components>

mainを実行した結果
Hello Manual Registar!


2.自動登録を使用した場合(プロジェクト名:ComponentAutoRegisterSample1)

(1)パッケージ構成
さっきと一緒


(2)各ソース
ClassAImpl.java
package org.yama.study.pk1;

public class ClassAImpl {
public void say() {
// ↓↓↓ 出力の文言を変えただけ。コンポーネントの自動登録には影響しない ↓↓↓
System.out.println("Hello Auto Registar!");
}
}

Driver.java
(さっきと一緒)

app.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
"http://www.seasar.org/dtd/components24.dtd">
<components>
    <component         class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
        <property name="autoNaming">
            <component class="org.seasar.framework.container.autoregister.DefaultAutoNaming"/>
        </property>
        <initMethod name="addClassPattern">
            <arg>"org.yama.study.pk1"</arg>
            <arg>".*Impl"</arg>
        </initMethod>
    </component>
</components>

mainを実行した結果
Hello Auto Registar!


3.いくつか解説

■自動登録する場合のapp.diconについて


app.dicon(抜粋)
        <initMethod name="addClassPattern">
            <arg>"org.yama.study.pk1"</arg>
            <arg>".*Impl"</arg>
        </initMethod>

1番目の引数は見てわかるとおり、自動登録するクラスのパッケージを指定しているが、
子供のパッケージも再帰的に検索するので、

        <initMethod name="addClassPattern">
            <arg>"org.yama.study"</arg>
            <arg>".*Impl"</arg>
        </initMethod>
や、

        <initMethod name="addClassPattern">
            <arg>"org"</arg>
            <arg>".*Impl"</arg>
        </initMethod>


でも、同様の動きとなった。

ただし、これはだめだった。

        <initMethod name="addClassPattern">
            <arg>""</arg>
            <arg>".*Impl"</arg>
        </initMethod>
デフォルトパッケージに自動登録したいクラスがあった場合、どうすればいいんだろう?
暇なときソースを追いかけてみるか。。。




■DefaultAutoNamingクラスの役割について

Driver.java(抜粋)
ClassAImpl ca = (ClassAImpl) container.getComponent("classA");

コンポーネントの自動登録をしない場合は、app.diconで明示的に「classA」という名前をコンポーネント名に設定している。一方、自動登録する場合には、「classA」というコンポーネント名は、どこにも設定していない。
にもかかわらず、「classA」というコンポーネント名が利用できるのは、app.diconで指定したDefaultAutoNamingクラスが、

app.dicon(抜粋)
        <property name="autoNaming">
            <component class="org.seasar.framework.container.autoregister.DefaultAutoNaming"/>
        </property>

自動でクラス名からコンポーネント名を導き出し、設定してるから。
サンプルの場合、以下のとおり。

・クラス名「org.yama.study.pk1.ClassAImpl」からパッケージ部分を除去し「ClassAImpl」という文字列を作成
    ↓

・「ClassAImpl」のImplを取り除き「ClassA」という文字列を作成

    ↓

・「ClassA」の先頭を小文字に変換し「classA」の出来上がり

この、変換ルールは、DefaultAutoNamingクラスのプロパティやメソッドで、ある程度変更可能。