かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

FF3の合間にS2のソースでも見てみよう

すぐ上のエントリで休むといっときつつきになってきた。
Seasar2のソースを読んでみよう!って思い立ってメモがわりにここにダラダラ書いていく。

org.seasar.framework.container.factory.S2ContainerFactory

とりあえず、コンソールアプリ大好きな俺がよく使うファクトリから見てみよう。
行数的にも1000行無い!やるぞ!!

createメソッド

とりあえず、しょっぱなに呼ぶメソッド!!
って4行しかないorz

    public static synchronized S2Container create(final String path) {
        if (!initialized) {
            configure();
        }
        return getProvider().create(path);
    }

未初期化なら初期化して、Providerさんに丸投げ!
いいね。この仕事っぷり。
俺もこういう仕事したいわw

ということでconfigureの仕事っぷりを確かめよう。

    public static void configure() {
        final String configFile = System.getProperty(FACTORY_CONFIG_KEY,
                FACTORY_CONFIG_PATH);
        configure(configFile);
    }

まだイマイチ仕事してない。
FACTORY_CONFIG_KEYのプロパティは、ほとんどの場合設定されない?だろうからFACTORY_CONFIG_PATH(s2container.dicon)がconfigFileに入る。
んで、それを引数にしてconfigureを呼び出す!
次は仕事してそうだ。

    public static synchronized void configure(final String configFile) {
        if (configuring) {
            return;
        }
        configuring = true;
        if (provider == null) {
            provider = new DefaultProvider();
        }
        if (defaultBuilder == null) {
            defaultBuilder = new XmlS2ContainerBuilder();
        }
        if (ResourceUtil.isExist(configFile)) {
            final S2ContainerBuilder builder = new XmlS2ContainerBuilder();
            configurationContainer = builder.build(configFile);
            configurationContainer.init();
            Configurator configurator;
            if (configurationContainer.hasComponentDef(Configurator.class)) {
                configurator = (Configurator) configurationContainer
                        .getComponent(Configurator.class);
            } else {
                configurator = new DefaultConfigurator();
            }
            configurator.configure(configurationContainer);
        }
        DisposableUtil.add(new Disposable() {
            public void dispose() {
                S2ContainerFactory.destroy();
            }
        });
        configuring = false;
        initialized = true;
    }

してるして。いっぱいしてる。
最初は、二重にやらないためのブロックか。
providerがDefaultProviderでdefaultBuilderがXmlS2ContainerBuilderかぁ。
S2ContainerBuilderをいじくってYAMLS2ContainerBuilderみたいなのを作ればXML以外を設定ファイルに出来るような響きだ。
だがおいかけない!
今日はさらっと見るだけ。

        if (ResourceUtil.isExist(configFile)) {
            final S2ContainerBuilder builder = new XmlS2ContainerBuilder();
            configurationContainer = builder.build(configFile);
            configurationContainer.init();
            Configurator configurator;
            if (configurationContainer.hasComponentDef(Configurator.class)) {
                configurator = (Configurator) configurationContainer
                        .getComponent(Configurator.class);
            } else {
                configurator = new DefaultConfigurator();
            }
            configurator.configure(configurationContainer);
        }

この部分で、S2Contaienrの設定を読み込んでるっぽい。
configuratorとかいうのが登録されてればそれを使うのか。
ここらへんも差し替えると色々できるのかな。実質しないだろうけどw

とりあえず、DefaultCOnfiguratorを覚えておこう。

最後に、自分自身を破棄するための場所に登録してる。

       DisposableUtil.add(new Disposable() {
            public void dispose() {
                S2ContainerFactory.destroy();
            }
        });

どうやって確実に破棄してんだろう?気になるのでDisposableUtilを見てみる。

org.seasar.framework.util.DisposableUtil

なんのことはない、リストに詰めて一括破棄!って機能があるだけだった。
誰かが何処かで後始末を責任もってするのだろう。
S2Containerのdestroyが呼ばれたあたりでやるのだろうか?
そんな風に妄想してみる。

public class DisposableUtil {

    protected static final LinkedList disposables = new LinkedList();

    public static synchronized void add(final Disposable disposable) {
        disposables.add(disposable);
    }

    public static synchronized void remove(final Disposable disposable) {
        disposables.remove(disposable);
    }

    public static synchronized void dispose() {
        while (!disposables.isEmpty()) {
            final Disposable disposable = (Disposable) disposables.removeLast();
            try {
                disposable.dispose();
            } catch (final Throwable t) {
                t.printStackTrace(); // must not use Logger.
            }
        }
        disposables.clear();
        Logger.dispose();
    }

    public static synchronized void deregisterAllDrivers() {
        try {
            for (Enumeration e = DriverManager.getDrivers(); e
                    .hasMoreElements();) {
                DriverManager.deregisterDriver((Driver) e.nextElement());
            }
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }
}

最後のDriverManagerからDriverを消すのは初見だった!
記憶の片隅においておこう。