[Seasar-user:2153] Re: injectDependencyについて

Koichi Kobayashi koichik
2005年 6月 9日 (木) 03:33:23 JST


小林 (koichik) です.

連投になっちゃいますが.

On Wed, 08 Jun 2005 10:16:53 +0900
Masataka Kurihara <[E-MAIL ADDRESS DELETED]> wrote:

>   一方、実装方法はともかく、コンポーネント定義が無いときに、その問題
> 解決をS2ContainerImplでなく、ComponentDeployerFactoryに持って
> いってもらうのが、なぜに「いやーん」なのかちょっと感覚を共有できてない。
> コンテナのカスタマイズポイントを一箇所に集中させたほうが、効率的かと
> 思います。

実際にカスタマイズやってみたのですが,集中しているようで
そうでもない感じ.ComponentDeployerFactory とカスタムの
ComponentDeployer で二つ実装することになりますよね.
コンテナ拡張する方だとクラス一つ作るだけ.1 対 2 (笑)

とりあえずコンテナ拡張方式のソースを掲載すると...

まずはカスタムなコンテナ.
----------------------------------------------------------------------
public class MyContainer extends S2ContainerImpl {
    public void injectDependency(Object outerComponent, Class componentClass) {
        ComponentDef[] componentDefs = findComponentDefs(componentClass);
        if (componentDefs.length > 0) {
            componentDefs[0].injectDependency(outerComponent);
        }
        else {
            ComponentDef cd = new ComponentDefImpl(componentClass);
            cd.setContainer(this);
            cd.setInstanceMode(ContainerConstants.INSTANCE_OUTER);
            cd.init();
            cd.injectDependency(outerComponent);
        }
    }
}
----------------------------------------------------------------------
TooMany〜 の時は最初のコンポーネント定義を使って injectDependency()
するようにしてます.この辺はポリシー次第.

そして上記のコンテナを有効にするための s2containerbuilder.dicon
----------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
  "http://www.seasar.org/dtd/components21.dtd">
<components>
  <component name="dicon"
    class="org.seasar.framework.container.factory.XmlS2ContainerBuilder"
  >
    <property name="rule">
      <component class="org.seasar.framework.container.factory.S2ContainerTagHandlerRule">
        <initMethod name="addTagHandler">
          <arg>"/components"</arg>
          <arg>
            <component class="org.seasar.framework.container.factory.ComponentsTagHandler">
              <property name="containerImplClass">@[E-MAIL ADDRESS DELETED]</property>
            </component>
          </arg>
        </initMethod>
      </component>
    </property>
  </component>
</components>
----------------------------------------------------------------------
これが怠いと言われればそうかもしれませんが,そう何回も書くものでも
ないと思います.

で,テスト用の 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>
  <component class="java.util.Map">
    #{"foo" : "FOO"}
  </component>
</components>
----------------------------------------------------------------------
特に意味なし.

そしてテストクラス.
----------------------------------------------------------------------
public class MyContainerTest extends TestCase {
    S2Container myContainer;

    public MyContainerTest() {
    }

    public MyContainerTest(String name) {
        super(name);
    }

    public void setUp() throws Exception {
        SingletonS2ContainerFactory.init();
        myContainer = SingletonS2ContainerFactory.getContainer();
    }

    public void test() throws Exception {
        assertTrue("1", myContainer instanceof MyContainer);
        Foo foo = new Foo();
        myContainer.injectDependency(foo);
        assertNotNull("2", foo.getMap());
    }

    public static class Foo {
        Map map;

        public Map getMap() {
            return this.map;
        }

        public void setMap(Map map) {
            this.map = map;
        }
    }
}
----------------------------------------------------------------------
カスタマイズのコードはどこにもありませんが,当然テストは成功します.
# S2TestCase を使っていないのは,S2TestCase は Builder 使わずに
# 独自にコンテナをセットアップするから.
# ここでカスタマイズを有効にするのは厳しいかも? (未調査)

とりあえず,当面見えている要求 (未定義コンポーネントに対する
injectDependency) については十分簡潔に対応できてると思うのですが
いかがでしょうか?

これと AssemblerFactory,ComponentDeployerFactory のカスタマイズを
組み合わせれば,自動バインディングの根性 UP も含めて概ね需要を
満たせるように思います.
ちなみに AssemblerFactory や ComponentDeployerFactory のカスタマイズも
s2containerbuilder.dicon に実装クラスを定義するだけで OK.
S2ContainerFactory もカスタマイズできます (笑).
Factory には PathResolver (相対パスから絶対パスへの変換などできる),
Builder には ResourceResolver (パスから InputStream を取得) を
設定することができます.


-- 
<signature>
    <name>Koichi Kobayashi</name>
    <e-mail>[E-MAIL ADDRESS DELETED]</e-mail>
</signature>




Seasar-user メーリングリストの案内