レベルエンター山本大のブログ

面白いプログラミング教育を若い人たちに

BLOCKVROCKリファレンス目次はこちら

簡易AOPフレームワークの作成

ちょっと現場で必要なので、CGLIBを使って簡易なAOPフレームワークを作ります。
トランザクション管理やコネクションのクローズを管理するフレームワークを作ることにします。
アノテーションを使ってプラグイン式に機能を追加できるようにします。

ただし、このフレームワークは対象オブジェクトの生成を管理しておく必要があります。
new演算子を使ってオブジェクト生成をすることを禁止し、
下記に紹介するFactoryクラスでオブジェクトを生成するルールを徹底します。

【準備】

以下のライブラリをダウンロードして、クラスパスに通しておきます。
■CGLIB
http://cglib.sourceforge.net/
・cglib-2.2.jar

■ASM
http://asm.ow2.org/
・asm-3.2.jar

【Factory.java

フレームワーク側のソースコードは以下です。
FactoryのgetInstanceメソッドによってオブジェクトを生成するというルール付けが必要です。

package kronosjp;
import java.lang.annotation.*;
import java.lang.reflect.Method;

import net.sf.cglib.proxy.*;

public class Factory{
	@SuppressWarnings("unchecked")
	public static <T> T getInstance(Class<T> targetClass){
		return (T) Enhancer.create(targetClass,new TransactionMethodIntercepter());
	}
}

class TransactionMethodIntercepter implements MethodInterceptor{
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before:" + method.getName());
        
        boolean isTransactional = method.isAnnotationPresent(Transactional.class);
        if (isTransactional){ System.out.println("transaction start"); }
        
        // オリジナルメソッドの実行
        Object result = proxy.invokeSuper(obj, args);
        
        if (isTransactional){ System.out.println("transaction end"); }
        
        System.out.println("after:"+ method.getName());
        return result;
    }
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Transactional{ }

【Start.java

ビジネスロジック側のソース。
@Transactionalメソッドをつけたメソッドがトランザクションメソッドになる仕組みです。

package kronosjp;

// 起動クラス
public class Start {
    public static void main(String[] args) throws Exception{
        LogicObject foo = Factory.getInstance(LogicObject.class);
        foo.logic();
    }
}

// ビジネスロジッククラス
class LogicObject {
    @Transactional
    public void logic(){
        System.out.println("do logic");
    }
}

【実行結果】

実行結果は以下のようになります。トランザクションの開始・終了処理がちゃんと呼び出されています。

before:logic
transaction start
do logic
transaction end
after:logic


追記
CGLIB は、Apach software License
Javasistは、Mozilla Public License

というところで、
商用利用するなら、CGLIBにもメリットはありそうですね。