
The Seasar Projectの全貌を探る(2)
第2回 DI+AOPを実現するSeasarV2
|
|
S2におけるAOP(S2AOP) |
続いて、S2によるAOPをどのようにして行えばよいかについて見ていきましょう。
AOPを行うツールには、AspectJやSpringなどがありますが、アスペクトをどのようにしてウィービングするかによって、大きく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パッケージ)
|
■既製のアスペクトの利用
表1に掲げた既製のアスペクトの中から、ThrowsInterceptorを継承して例外処理を行うアスペクトを実装する方法を紹介します。サンプルとして用いるのは、平均値を求めるアプリケーションです。そのソースコードをリスト6、diconファイルをリスト7に示します。このとき、もし平均値を求める際に、計算の基になる引数がまったく設定されていなかったらメッセージを表示するアスペクトを実装してみましょう。
まず、きちんと引数を設定してこのアプリケーションを実行した結果を以下に示します。
| 実行結果 |
|
|
続いて引数を設定しないでこのアプリケーションを実行した結果を以下に示します。
| 実行結果 |
|
|
実行結果の最初の2行が、これから作成するアスペクトにより出力されたメッセージです。平均値を求めようにも引数が設定されていませんので、NullPointerExceptionが発生します。それをインターセプタで受け取って「getAverageメソッドで平均値を計算できませんでした」というメッセージを表示しているわけです。
この処理を行うインターセプタをリスト8のように作成しました。ThrowsInterceptorを継承して例外処理を行うアスペクトを作成する場合は、必ずhandleThrowableというメソッドを実装することになっています。この部分に例外が発生した場合の処理を記述します。
リスト8では、このメソッドの第1引数をThrowableにしていますので、すべての例外をこのメソッドで受け付けて処理することになりますが、この引数を別のExceptionクラスに変更すれば、その例外(とそのサブクラス)のみを受け付けるメソッドにすることができます。複数の種類の例外を受け付けるようにしたい場合は、それぞれの例外に応じたhandleThrowableメソッドを複数実装することで、それに対応できるようになっています。
diconファイルでアスペクトの指定をするには、<component>〜</component>間に<aspect>タグを記述します。pointcut属性にポイントとカットとなるメソッド名を記述します。そして<aspect>〜</aspect>間には、事前にインターセプタをコンポーネントとして記述したときの名称(name属性の値)か、<component>タグ自体を記述します。これによりコンポーネントにアスペクトが設定されます。なお、1つのコンポーネントに複数のアスペクトを設定する場合は<aspect>タグが複数記述されることになります。
| リスト6 平均値を求めるアプリケーション [AverageImpl.java] |
package myfirst.aop; |
| リスト7 diconファイル |
<?xml version="1.0" encoding="Shift_JIS"?> |
| リスト8 ThrowsInterceptorを継承して作成したインターセプタ [noArgsInterceptor.java] |
package myfirst.aop; |
■独自のアスペクトを作成する
今度は、既製のものではない独自のアスペクトを作成してみましょう。作成するのは、引数の最大値を求めるアスペクトです。ここではAbstractInterceptorを継承して作成する例(リスト9)を紹介します。
リスト9の場合でも、MethodInterceptorインターフェイスを実装する場合でも、アスペクトとしての処理は必ずinvokeメソッドに実装します。そしてその内部では、ポイントカットとして指定されたメソッドをproceedメソッドで実行し、その結果を返す、というのが基本的な流れです。
proceedメソッドの前に何らかの処理を実行するものはBeforeアドバイスとなり、このメソッドの後で何らかの処理を実行するものはAfterアドバイスになります。proceedメソッドの前後どちらとも何らかの処理が行われるものはAroundアドバイスとなります。リスト9の場合は先にproceedメソッドが実行されていますので、これはAfterアドバイスということになります。
これをアスペクトとしてリスト7に追加したものがリスト10です。アスペクト自身の<component>タグと、それをアスペクトに指定する<aspect>タグを確認してみてください。
| リスト9 AbstractInterceptorを継承して作成したアスペクト(引数の最大値を求める) [MaxValueIntercepter.java] |
package myfirst.aop; |
| リスト10 diconファイルにリスト9のアスペクトを追加したもの [average.dicon] |
<components> |
今回はS2におけるDIとAOPについて見てきました。次回は、S2におけるデータベース関連の機能を見ていきます。
| 3/3 |
|
INDEX |
||
| 第2回 DI+AOPを実現するSeasar V2 | ||
| Page1 S2のダウンロードと環境設定 S2におけるDI |
||
| Page2 DIの作成例 |
||
| Page3 S2におけるAOP(S2AOP) |
||
Seaser Projectの全貌を探る バックナンバー
| Java Solution全記事一覧 |
TechTargetジャパン
- Scalaのパッケージ、アクセス修飾子、オブジェクト継承 (2012/5/22)
インポート、パッケージオブジェクト、抽象クラス/抽象メソッド、オーバーライド、final、シールドクラスなども - 基幹系システムでCloud SQLは使えるか試してみた (2012/5/17)
サンプルとしてMRPシステムを作成して動かし、「再帰呼び出し」などのパフォーマンスを測定して検証してみます - アジャイル管理ツール9選+Pivotal Tracker入門 (2012/5/14)
群雄割拠のアジャイルプロジェクト管理ツールを9つ紹介し、特に注目を集めているPivotal Trackerの基本的な使い方を解説します - サーバサイドJSやJavaでWebアプリが作れるXPages (2012/5/11)
Notes/Dominoの資産をサーバサイドJavaScriptやJavaで操作し、HTMLやJavaScript、CSSをUIにできる技術を紹介
|
|
キャリアアップ
スポンサーからのお知らせ
- - PR -
イベントカレンダー
- - PR -
