[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 <kurihara @ gluegent.com> 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">@custom.MyContainer @ class</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>koichik @ improvement.jp</e-mail>
</signature>
    
    
Seasar-user メーリングリストの案内