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で書けばいいかなとか、そんな感じに思えてきた。
設定を外部ファイル化しすぎると今度はやっぱりソースに書いた方がいいと思えてきてループる。