ログ日記

作業ログと日記とメモ

SeasarでインターフェースをCreatorの対象にする

プロパティファイルを読み込んでインターフェースを実装したクラスからプロパティ値を受け取るということをやってみた。


インターセプタークラスを作る。

package app.lib;

import java.util.Properties;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.seasar.framework.env.Env;
import org.seasar.framework.exception.ResourceNotFoundRuntimeException;
import org.seasar.framework.util.ResourceUtil;

public class ConstantsInterceptor implements MethodInterceptor {
    private final String suffix = Env.getValue();
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // invocationのターゲットはインターフェース
        String className = invocation.getThis().getClass().getName()
               .replaceAll("\\$\\$EnhancedByS2AOP\\$\\$[a-f0-9]*", "");
        String filePath = className.replaceAll("\\.", "/");
        Properties props;
        try {
            // 環境別ファイルの読み込み
            props = ResourceUtil.getProperties(filePath + "_" + suffix + ".properties");
        }catch (ResourceNotFoundRuntimeException e){
            // デフォルトファイルの読み込みでの例外はキャッチしない
            props = ResourceUtil.getProperties(filePath + ".properties");
        }
        // この方法だとキャッシュはしない
        return props.getProperty(invocation.getMethod().getName());
    }
}

あとは設定ファイルを書く。


app.dicon(設定ファイルを分けるならapp-aop.dicon)

  <component name="constantsInterceptor" class="app.lib.ConstantsInterceptor"/>


creator.dicon

        <component class="org.seasar.framework.container.creator.HelperCreator">
                        <initMethod name="setEnableInterface"><arg>true</arg></initMethod>
        </component>


customizer.dicon

    <component name="helperCustomizer" class="org.seasar.framework.container.customizer.CustomizerChain">
        <initMethod name="addCustomizer">
            <arg>traceCustomizer</arg>
        </initMethod>
        <initMethod name="addCustomizer">
            <arg>
                <component class="org.seasar.framework.container.customizer.AspectCustomizer">
                    <property name="interceptorName">"constantsInterceptor"</property>
                </component>
            </arg>
        </initMethod>
    </component>


あとはhelperディレクトリ以下にインターフェースとプロパティファイルを作成するとコンポーネントとして使えるようになる。
helper/ConstantsHelper.java

package app.myapp.helper;

public interface ConstantsHelper {
    public String hoge();
}

helper/ConstantsHelper.properties

hoge = product_hoge

helper/ConstantsHelper_ct.properties

hoge = ct_hoge


利用側

package app.myapp.service;

public class MyService {
    @Resource
    private ConstantsHelper constantsHelper;

    public void hogeService(){
        System.out.println(constantsHelper.hoge());
    }
}


ここまでやってみて、やっぱりS2Configがいいかなとか、そもそもプロパティファイルを使わずにヘルパークラスのコンストラクタでEnvを読み取って値を設定してもいいかなとか、複数箇所から参照されるわけではない値なら上の例だとMyServiceクラスに直接finalで書けばいいかなとか、そんな感じに思えてきた。
設定を外部ファイル化しすぎると今度はやっぱりソースに書いた方がいいと思えてきてループる。