検索
連載

DI+AOPを実現するSeasarV2Seaser Projectの全貌を探る(2)(3/3 ページ)

Seasar(シーサー)は、国内のコミュニティ「The Seasar Project」によって開発が行われているオープンソースプロダクトだ。DI+AOPコンテナとして評価が高いSeasarV2は、J2EE開発の現場にも影響力を持ち始めた。例えば電通国際情報サービスがSeasar Projectを正式に支援することを表明し、2005年6月からは同社による商用サポートサービスが開始されている。本連載では、同プロジェクトの代表的なプロダクト紹介していく。(編集局)

Share
Tweet
LINE
Hatena
前のページへ |       

S2におけるAOP(S2AOP)

 続いて、S2によるAOPをどのようにして行えばよいかについて見ていきましょう。

 AOPを行うツールには、AspectJSpringなどがありますが、アスペクトをどのようにしてウィービングするかによって、大きく2つのタイプに分けることができるでしょう。1つは、AspectJのようにアスペクトを別のクラスとして作成しておいて、ウィービングを一括して行うタイプです。そしてもう1つは、アスペクトをインターセプタ(Interceptor)として作成しておき、DIコンテナでインスタンスを生成する際にこれをウィービングするタイプです。S2やSpringはこちらのタイプに分けることができます。

 S2では、よく利用されると思われるアスペクトがあらかじめ既製のインターセプタとして用意されています。その一覧を表1に掲げます。S2におけるインターセプタを用いたアスペクトは、基本的に本質的関心事のメソッドを実行する前後に割り込ませて実行させるAroundアドバイスに相当します。これらのインターセプタの使用法はSeasarプロジェクトのドキュメント「S2AOPで用意されているInterceptor」(http://www.seasar.org/aop.html#AOPInterceptor)を参照してください。

 独自にアスペクトを実装する場合も、org.aopalliance.intercept.MethodInterceptorインターフェイスを実装するか、すでにこのインターフェイスを実装済みの抽象クラスorg.seasar.framework.aop.interceptors.AbstractInterceptorを継承するかのどちらかで行います。この場合は、実装の方法によってBeforeアドバイスにしたり、Afterアドバイスにしたりすることは可能です。

表1 S2で用意されているインターセプタ
(すべてorg.seasar.framework.aop.interceptorsパッケージ)
クラス名 働き
TraceInterceptor メソッドの実行をログに出力するトレース処理を行う
ThrowsInterceptor これを継承して例外発生時の処理を記述する
TraceThrowsInterceptor 例外の発生をトレースする
MockInterceptor オブジェクトをモックとして振る舞わせる(テスト用)
DelegateInterceptor ほかのクラスのメソッドに処理を委譲する
PrototypeDelegateInterceptor S2コンテナからインスタンスを取得して、そのインスタンスのメソッドに処理を委譲する
SyncInterceptor メソッド呼び出しを同期させる
InterceptorChain 複数のインターセプタをネストさせて実行する

既製のアスペクトの利用

 表1に掲げた既製のアスペクトの中から、ThrowsInterceptorを継承して例外処理を行うアスペクトを実装する方法を紹介します。サンプルとして用いるのは、平均値を求めるアプリケーションです。そのソースコードをリスト6、diconファイルをリスト7に示します。このとき、もし平均値を求める際に、計算の基になる引数がまったく設定されていなかったらメッセージを表示するアスペクトを実装してみましょう。

 まず、きちんと引数を設定してこのアプリケーションを実行した結果を以下に示します。

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 続いて引数を設定しないでこのアプリケーションを実行した結果を以下に示します。

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 実行結果の最初の2行が、これから作成するアスペクトにより出力されたメッセージです。平均値を求めようにも引数が設定されていませんので、NullPointerExceptionが発生します。それをインターセプタで受け取って「getAverageメソッドで平均値を計算できませんでした」というメッセージを表示しているわけです。

 この処理を行うインターセプタをリスト8のように作成しました。ThrowsInterceptorを継承して例外処理を行うアスペクトを作成する場合は、必ずhandleThrowableというメソッドを実装することになっています。この部分に例外が発生した場合の処理を記述します。

 リスト8では、このメソッドの第1引数をThrowableにしていますので、すべての例外をこのメソッドで受け付けて処理することになりますが、この引数を別のExceptionクラスに変更すれば、その例外(とそのサブクラス)のみを受け付けるメソッドにすることができます。複数の種類の例外を受け付けるようにしたい場合は、それぞれの例外に応じたhandleThrowableメソッドを複数実装することで、それに対応できるようになっています。

 diconファイルでアスペクトの指定をするには、<component>〜</component>間に<aspect>タグを記述します。pointcut属性にポイントとカットとなるメソッド名を記述します。そして<aspect>〜</aspect>間には、事前にインターセプタをコンポーネントとして記述したときの名称(name属性の値)か、<component>タグ自体を記述します。これによりコンポーネントにアスペクトが設定されます。なお、1つのコンポーネントに複数のアスペクトを設定する場合は<aspect>タグが複数記述されることになります。

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

独自のアスペクトを作成する

 今度は、既製のものではない独自のアスペクトを作成してみましょう。作成するのは、引数の最大値を求めるアスペクトです。ここではAbstractInterceptorを継承して作成する例(リスト9)を紹介します。

 リスト9の場合でも、MethodInterceptorインターフェイスを実装する場合でも、アスペクトとしての処理は必ずinvokeメソッドに実装します。そしてその内部では、ポイントカットとして指定されたメソッドをproceedメソッドで実行し、その結果を返す、というのが基本的な流れです。

 proceedメソッドの前に何らかの処理を実行するものはBeforeアドバイスとなり、このメソッドの後で何らかの処理を実行するものはAfterアドバイスになります。proceedメソッドの前後どちらとも何らかの処理が行われるものはAroundアドバイスとなります。リスト9の場合は先にproceedメソッドが実行されていますので、これはAfterアドバイスということになります。

 これをアスペクトとしてリスト7に追加したものがリスト10です。アスペクト自身の<component>タグと、それをアスペクトに指定する<aspect>タグを確認してみてください。

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 今回はS2におけるDIとAOPについて見てきました。次回は、S2におけるデータベース関連の機能を見ていきます。


前のページへ |       

Copyright © ITmedia, Inc. All Rights Reserved.

ページトップに戻る