今回は、実際に自分でAOPで織り込む機能を実装してみましょう!
織り込むクラスをインターセプターと呼びます。
ここでは、指定のメソッドの実行ログを取るインターセプターを作ってみます。
早速、実装を見てみましょう。
【インターセプタコードサンプル】
package aop; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.apache.log4j.Logger; public class LoggingInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { // Logger log = Logger.getLogger(invocation.getMethod().getName()); log.info("logging_start: "); log.info("logging_method: '" + invocation.getMethod().getName() + "' of class[" + invocation.getThis().getClass().getName() + "]"
); //メソッド実行 Object ret = null; try{ ret = invocation.proceed(); }catch(Exception e){ log.error("logging_exception: ", e); throw e; }finally{ log.info("logging_end: return=" + ret); } return ret; } }
【Spring設定ファイルの記述例】
<bean id="logging" class="aop.LoggingInterceptor" />
<aop:config>
<aop:advisor pointcut="execution(* execute(..))" advice-ref="logging" />
</aop:config>
【説明】
自作でインターセプタを作成するときは、MethodInterceptor をimplemetnsして作成します。
これは、メソッド処理の実施前後を乗っ取るときに使用します。
他にも、メソッドの処理前、処理後、例外が発生したときだけ実施する、などいくつか種類があります。
といっても、MethodInterceptor を使用すれば処理前後、例外発生時、どれでも処理を織り込めます。
なので、面倒ならこれをいつでも使用してもいいかもしれません。
ただ、クラスの意味合いを明確にしたい場合は、それぞれの処理にあったinterfaceを使用しましょう。
さて、実際の実装ですが、invokeメソッドを記述するだけです。
メソッドには、MethodInvocation が渡ってきます。
これには、実際にメソッドに渡ってくる引数や、メソッド名など様々な情報が入っています。
これを使用すればいろいろできます!
<注意点>
注意点は、織り込む前の本当のメソッドの処理を以下のようにインターセプタ内で実行する必要があることです。
invocation.proceed();
これを記述しないと、本当のメソッドの処理が実行されません。
【出力例】
2009-04-05 15:44:38,843 [http-8080-Processor24] INFO execute - logging_start:
2009-04-05 15:44:38,843 [http-8080-Processor24] INFO execute - logging_method: 'execute' of class[presentation.action.MemberSearchAction]
2009-04-05 15:44:38,843 [http-8080-Processor24] INFO execute - logging_end: return=ForwardConfig[name=input,path=/WEB-INF/jsp/member_search_input.jsp,redirect=false,module=null,extends=null,catalog=null,command=null]
返り値の値まで出力されています!
【メリット】
上記のSpringの設定で記述したのは、StrutsのActionのexceuteに織り込みました。
普通にやろうとすると、StrutsのActionの派生クラスにすべてログの処理を入れるか、もしくは
基底クラスを作成して、そちらに共通処理用のメソッドを記述するしかありません。
後者の方がやり方としてはマシなやり方です。
しかし、基底クラスを必ず継承しないといけないという制限が付きます。
これは、システムが大きくなって処理を統一化しにくくなったときに大きな制限になります。
AOPによって設定のみで自由にログを出力するメソッドを変更したり、ログ出力を止めることがことができるのはかなりなメリットになるのです。
AOPの概要や注意点は、以下の参考を見てみてください。
参考:
・Springに付属のAOPサンプルのログトレースを動かすには? (用意されたクラスを使用する方法)