JBossAOP を Groovy から利用

JBoss の AOP 環境 JBossAOP(1.5.5 GA)を Groovy(1.0)から以下のようにして使ってみる。

  • Groovy のスクリプトでインターセプターを定義(org.jboss.aop.advice.Interceptor の実装クラス)
  • JBossAOP の DynamicAOP 機能を使って Groovy スクリプトの実行時に Java クラスに AOP を適用

まず、AOP 適用対象とする Java クラスを適当に作成してコンパイルしておく。

public class TestData {
    public void printData() {
        System.out.println("data");
    }
}

次に、AOP の適用対象を指定するための jboss-aop.xml ファイルを作成し(DynamicAOP の利用に必要)、上記で作成した Java クラスの全メソッドを適用対象とする。

<?xml version="1.0" encoding="UTF-8"?>
<aop>
  <prepare expr="all(TestData)"/>
</aop>

次に、Groovy スクリプトを作成。

import org.jboss.aop.AspectManager
import org.jboss.aop.advice.AdviceBinding
import org.jboss.aop.advice.Interceptor
import org.jboss.aop.joinpoint.Invocation

//インターセプターの定義
class TestInterceptor implements Interceptor {
    def String getName() {
        "TestInterceptor"
    }

    def invoke(Invocation inv) {
        println "- before -"

        def result = inv.invokeNext()

        println "- after -"

        result
    }
}

data = new TestData()
//AOP 適用前(1回目の printData 実行)
data.printData()

//DynamicAOP による AOP の動的適用
bind = new AdviceBinding("execution(* *->printData(..))", null)
bind.addInterceptor(TestInterceptor)
AspectManager.instance().addBinding(bind)

//AOP 適用後(2回目の printData 実行)
data.printData()

ここで、普通に groovy コマンドで実行しても DynamicAOP は適用されない。

DynamicAOP 機能を利用するには、java コマンドで Instrumentation 機能を使用する必要があり、そのためには groovy コマンドで java コマンドのオプション指定用に用意されている JAVA_OPTS 環境変数を使う事になる。

というわけで、JAVA_OPTS 環境変数に以下のような値を設定する。(jboss.aop.path は jboss-aop.xml ファイルの配置場所を指定)

>set JAVA_OPTS=-javaagent:C:\jboss-aop_1.5.5.GA\lib-50%\jboss-aop-jdk50.jar -Djboss.aop.path=.

この状態で groovy スクリプトを groovy コマンドで実行すると、以下のような結果となり、2回目の printData の実行時に Groovy スクリプトで定義したインターセプターが適用されており、DyamicAOP に成功している事がわかる。

>groovy test.groovy
data
- before -
data
- after -