GroovyだらけでSeasar

SeasarBuilderをちょびっと変更してgroovyスクリプトからつくったクラスをコンテナに登録しよう。

  • SeasarBuilderを変更したCustomizedSeasarBuilder groovyという属性が指定されたらgroovyファイルからClassを生成してコンテナに登録。
   // このメソッド変更
   private ComponentDef setupComponentDef(Map attributes) {
       ComponentDef def = null;
       
       String groovy = (String) attributes.get("groovy");
       Class cls;
       if (groovy != null) {
           cls = createClass(groovy + ".groovy");
       } else {
           cls = (Class) attributes.get("class");
       }
       
       // snip
   }

   // このメソッド追加
   private Class createClass(String groovyPath) {
        GroovyClassLoader groovyLoader =
            new GroovyClassLoader(getClass().getClassLoader());
        File file = ResourceUtil.getResourceAsFile(groovyPath);
        try {
            return groovyLoader.parseClass(file);
        } catch (CompilationFailedException e) {
            throw new SeasarBuilderException(
                    "can't create Class object from '" + groovyPath + "'", e);
        } catch (IOException e) {
            throw new SeasarBuilderException(
                    "can't create Class object from '" + groovyPath + "'", e);
        }
    }
<
  • app.groovy 定義ファイル。上記CustomizedSeasarBuilderを使う。componentのgroovyという属性にgroovyファイルのパスを指定。
import study.seasar.*
import org.seasar.framework.aop.interceptors.*

new CustomizedSeasarBuilder().components() {
    component(class: TraceInterceptor, name: "trace")
    component(groovy: "study/seasar/Calculator", name: "calc") {
        aspect(advice: "trace")
    }
}
class Calculator {
    int add(i, j) {
        return i + j
    }
}
  • Client.groovy コンテナを使うClientもgroovyにしちゃおう
package study.seasar;
import org.seasar.framework.container.factory.S2ContainerFactory;

public class Client {
    static void main(String[] args) {
        container = S2ContainerFactory.create("study/seasar/app.groovy")
        container.init()
        try {
            hoge = container.getComponent("calc")
            num = hoge.add(10,50)
            println num
        } finally {
            container.destroy()
        }
    }
}
  • 実行結果
BEGIN Calculator#invokeMethod(add, [Ljava.lang.Object;@17431b9) END Calculator#invokeMethod(add, [Ljava.lang.Object;@17431b9) : 60 60
本当はinvokeMethodが呼ばれているということがわかる。 Groovyを使うとなんだかちょっとうれしいカンジ。
  • 追記
groovyスクリプトからgroovyスクリプト呼び出すのってなんかいやだ。そんなときこそDIコンテナで依存性注入しとけばいいのでは。インタフェースもつかえるはずだし。