S2GroovyBuilderでClosureを使う
adviceにClosureを渡せるところがすてきだと思う。
こんなことをしてみた。
CalcClient
package taedium.study; import org.seasar.framework.container.S2Container; import org.seasar.framework.container.factory.S2ContainerFactory; import test.org.seasar.extension.openamf.Calculator; public class CalcClient { private static final String PATH = "taedium/study/CalcClient.groovy"; public static void main(String[] args) { S2Container container = S2ContainerFactory.create(PATH); Calculator calc = (Calculator) container.getComponent(Calculator.class); int answer = calc.plus(10,20); System.out.println(answer); } }
クラスに属さないメソッドの定義(defを使ったもの)の中からはそのスコープの外で定義された変数を参照できないのでメソッドからDEBUGやTRACEを参照するためにクラスをつくる。
CalcClient.groovy
import org.seasar.framework.aop.interceptors.* import org.seasar.groovy.* import test.org.seasar.extension.openamf.CalculatorImpl // Container new SeasarBuilder().components(){ ad = new Advices(); // 下で定義したclass include("j2ee.dicon") component(class: TraceInterceptor, name: "trace") component(class: CalculatorImpl){ aspect(advice: "j2ee.requiredTx") aspect(advice: ad.trace()) aspect(advice: ad.intercept()) } } class Advices { TRACE = true DEBUG = true /* DefaultのClosure、interceptされてるmethodを実行するだけ */ invocation = { return it.proceed() } /* * TRACEがtrueならばTraceInterceptorのComponent登録名(String)を返す * TRACEがfalseならばDefaultのClosureを返す */ Object trace() { if (TRACE) { return "trace" } return invocation } /* * DEBUGがtrueならば任意のClosureを返す * DEBUGがfalseならばDefaultのClosureを返す */ Object intercept() { if (DEBUG) { return { return 9999999 } } return invocation } }
実行結果(TRACEもDEBUGもtrueの場合)
BEGIN est.org.seasar.extension.openamf.CalculatorImpl#plus(10, 20) END est.org.seasar.extension.openamf.CalculatorImpl#plus(10, 20) : 9999999 9999999
実行結果(TRACEもDEBUGもfalseの場合)
30
ひさびさにSeasarさわった。
diconからgroovyをincludeできることとその逆ができることを確認。適材適所で使い分けができますね。