[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 メーリングリストの案内