Container の組み立て

 難しいところは省略していくよー。 S2ContainerFactory#createからProvider#build を呼び出す。お、S2ContainerBuilder という如何にもな名前のインターフェースを発見。SingletonS2ContainerFactory#init で、設定した configPath の dicon ファイルを解析します。実態は XmlS2ContainerBuilder で、 TagHandlerContext にパースした dicon のコンテキスト情報(つまり, S2Container!)を保持します。AbstractTagHandler が SAX で解析するときのハンドラで、複数のタグに対応しています。例えば以下のクラスが存在します。例えばアスペクトってどうやって織り込まれてるの?って確認したいときは, AspectTagHandler から読み進めると良いんじゃないかと思います。アスペクトに関しては後日読もうかと思っています。

  • ArgTagHandler
  • AspectTagHandler
  • ComponentsTagHandler
  • ComponentTagHandler
  • IncludeTagHandler
  • InterTypeTagHandler
  • MetaTagHandler
  • MethodTagHandler
  • PropertyTagHandler

 Seasar の dicon ファイルでは Components がルートタグになっている(と思う・・・調べてない)ので, まず ComponentsTagHandler で Container を生成します。実際のコンテナの実装クラスは書いていませんが、ここが Container の生まれる場所ですね。勿論, 親のコンテナがあれば親もセットされます。

protected S2Container createContainer() {
    return (S2Container) ClassUtil.newInstance(containerImplClass);
}

 次に, ComponentTagHandler で順次コンポーネント定義をコンテキストに push していきます。今回は面倒なので ComponentTagHandler のみ見てみます。取り敢えず大事そうなところだけ抽出してみましょう。タグの開始に対するコールバックとして, コンテキストに ComponentDef を push します。

public void start(TagHandlerContext context, Attributes attributes) {
    String className = attributes.getValue("class");
    Class componentClass = null;
    if (className != null) {
        componentClass = ClassUtil.forName(className);
    }
    String name = attributes.getValue("name");
    ComponentDef componentDef = createComponentDef(componentClass, name);
    String instanceMode = attributes.getValue("instance");
    if (instanceMode != null) {
        componentDef.setInstanceDef(InstanceDefFactory
                .getInstanceDef(instanceMode));
    }
    String autoBindingName = attributes.getValue("autoBinding");
    if (autoBindingName != null) {
        componentDef.setAutoBindingDef(AutoBindingDefFactory
                .getAutoBindingDef(autoBindingName));
    }
    context.push(componentDef);
}

 タグが終了したら, コンポーネント定義を S2Container に登録します。ここでようやく S2Container#register が登場しました。式の解析なども行われているようですが、特に興味も無いので飛ばします。

public void end(TagHandlerContext context, String body) {
    ComponentDef componentDef = (ComponentDef) context.pop();
    String expression = null;
    if (body != null) {
        expression = body.trim();
        if (!StringUtil.isEmpty(expression)) {
            componentDef
                    .setExpression(createExpression(context, expression));
        } else {
            expression = null;
        }
    }
    if (context.peek() instanceof S2Container) {
        S2Container container = (S2Container) context.peek();
        container.register(componentDef);
    } else {
        ArgDef argDef = (ArgDef) context.peek();
        argDef.setChildComponentDef(componentDef);
    }
}

 S2Container で登録された ComponentDef は, S2ContainerImpl#componentDefMap に保持されます。次はここからどのように ComponentDef を読み込み、クラスを生成してインジェクションされるか見てみましょう。