AOP(Aspect Oriented Programming)を簡単にいうと元のソースコードに手を加えることなく、透明なサービスを提供する技術といえるのではないかと思います。透明というのは、使っている側からその存在が見えないという意味です。キーとなる概念には次のようなものがあります。
プログラム中に挿入されるコードを表します。Adviceには幾つか種類がありますが、Seasarでは、メソッド呼び出しの前後にコードを挿入することのできるAroundAdviceだけをサポートします。AOPはこれまでにない考え方なので、最初から複雑にすると受け入れられにくくなるのではと思ったためです。
プログラム中に特定のコードを挿入するポイントを表します。AdviceはJoinpointから引数やメソッドの情報を取得することができます。
Adviceをどこに挿入するのかを定義します。
AdviceとPointcutを関連付けます。
それでは、Seasarに最初からついているトレースのためのAdviceを見てみましょう。
package org.seasar.framework.aop.advices;
import org.seasar.framework.aop.AroundAdvice;
import org.seasar.framework.aop.Joinpoint;
public class TraceAdvice implements AroundAdvice {
public Object invoke(Joinpoint joinpoint) throws Throwable {
StringBuffer buf = new StringBuffer(100);
buf.append(joinpoint.getTargetClass().getName());
buf.append("#");
buf.append(joinpoint.getMethod().getName());
buf.append("(");
Object[] args = joinpoint.getArgs();
if (args != null && args.length > 0) {
for (int i = 0; i < args.length; ++i) {
buf.append(args[i]);
buf.append(", ");
}
buf.setLength(buf.length() - 2);
}
buf.append(")");
System.out.println("BEGIN " + buf);
try {
Object ret = joinpoint.proceed();
buf.append(" : ");
buf.append(ret);
return ret;
} catch (Throwable t) {
buf.append(" Throwable:");
buf.append(t);
throw t;
} finally {
System.out.println("END " + buf);
}
}
}
Adviceを実装するには、AroundAdviceをimplementsしてinvokeメソッドを実装します。JointpointのgetTarget()、getTargetClass()、getMethod()、getArgs()で対象となるオブジェクト、オブジェクトのクラス、メソッド、引数を取得できます。proceed()を呼び出すと実際のメソッドが呼び出され実行結果を取得することができます。
それでは、DateクラスにTraceAdviceを適用します。対象となるメソッドはgetTime()とします。
Pointcut pointcut = new PointcutImpl(new String[]{"getTime"});
Aspect aspect = new AspectImpl(new TraceAdvice(), pointcut);
AopProxy aopProxy = new AopProxy(Date.class, new Aspect[]{aspect});
Date proxy = (Date) aopProxy.create();
proxy.getTime();
PointcutImplのコンストラクタの引数で対象となるメソッド名を指定(複数可)します。AutoNumberImplのようにインターフェースを実装しているなら、new PointcutImpl(AutoNumberImpl.class)のようにクラスを指定することで、そのクラスが実装しているインターフェースのメソッドをすべて自動的に適用させることもできます。メソッド名には正規表現(JDK1.4のreqex)も使えます。
AopProxyのコンストラクタで、対象となるクラスとAspectの配列を指定します。その後、create()でAspectが適用されたProxyオブジェクトを取得できます。Aspectは透明なサービスなんだということが分かってもらえると思います。