かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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を消すのは初見だった!
記憶の片隅においておこう。