[Seasar-user:722] Re: instance="prototype" にはまった私

B rmail.plala.or.jp suga suga_k
2004年 5月 1日 (土) 01:23:07 JST


スガです。

勉強がてらに追いかけてみました。


On Fri, 30 Apr 2004 20:45:44 +0900
jazzatny <[E-MAIL ADDRESS DELETED]> wrote:

> 2)次に、MaximDisplayの引数なしコンストラクタのコメント
> をはずし実行すると、
> java.lang.NullPointerException
>     at test.seasar.MaximDisplay.setMaximStr
>        (MaximDisplay.java:17)
> とExceptionをはきます。これはmaxim.xmlに
> autoBinding="constructor"もしくは"auto"を
> 設定しても同様です。

ここは prototype かどうかは関係なく、

org.seasar.framework.container.assembler.
    AutoConstructorAssembler#getSuitableConstructor()

の中で明示的に

if (tempArgSize == 0) {
    return null;
}

としていますので、ドキュメントの間違いではないかと思います。
# ちなみに上の三行を削れば引数有りを優先します。


少なくとも現状では、引数無しのコンストラクタがある場合、必ず
引数無しのコンストラクタが使われます。

autoBinding="constructor" だと初期化はそこで終わります。

"auto", "property" だと引き続き property による初期化が実行されます。
なお当然ながら、このとき xml で

<component name="display" instance="prototype" class="MaximDisplay">
    <property name="maxim">maxim</property>
</component>

とし、setter

MaximDisplay#setMaxim(IMaxim maxim) {
    maxim_ = maxim;
}

を作る必要があります。


---------------------------------------------------------------
> 3)更に、maxim.xmlのコンポーネントname="display"に
> <arg>maxim</arg>を設定し実行すると、
> ++ しています。
> ++ しています。
> ++ しています。
> と出力されます。これもmaxim.xmlに
> autoBinding="constructor"、"auto"を設定しても同様です。

これは Sel を使った場合のみの現象で、バグっぽいです。
# XML でのコンポーネント指定 = Sel を使う


org.seasar.framework.container.impl.ArgDefImpl#getValue()
if (childComponentDef_ != null) {
    return childComponentDef_.getComponent();
}
if (value_ != null) {
    return value_;
}
if (expression_ != null) {
    Expression exp = new SelParser(expression_).parseExpression();
    setValue(exp.evaluateValue(container_.getSelContext()));  //-- (1)
    //** ここで getComponent() の結果をセットしてしまっているため、
    //** 次以降は生成されずに同じ物がセットされる。
    //** singleton ならこれで問題ない。
}
return value_;

(1) の行の内部処理はここ

org.seasar.framework.container.impl.
    S2ContainerSelContext#getVariable(String name)
if ("this".equals(name)) {
    return this_;
} else {
    return container_.getComponent(name);
}



XML の display 設定部分を抜き出すと

<component name="display" instance="prototype" class="MaximDisplay">
    <arg>maxim</arg>
</component>

この設定を Java コードで行うとこのようになるでしょう。

ComponentDefImpl cd = new ComponentDefImpl(MaximDisplay.class, "display");
cd.setInstanceMode(ComponentDefImpl.INSTANCE_PROTOTYPE);
ArgDefImpl argDef = new ArgDefImpl();
argDef.setExpression("maxim"); //-- (2)
cd.addArgDef(argDef);
container.register(cd);

(2) の部分は、現状では実質下記と同じ動作をします。

argDef.setValue(container.getComponent("maxim"));

で、意図した動作をするのはこうではないでしょうか。

argDef.setChildComponentDef(container.getComponentDef("maxim"));


--------------------------------------------------------------
 e-mail: [E-MAIL ADDRESS DELETED]
                                              スガ
--------------------------------------------------------------



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