JavaのWebアプリケーション開発フレームワークによる、Webサイト開発の顛末記です。

EclipseのMavenを使った、Spring-MVC、Thymeleaf、MyBatis 等のプログラミングテクニックを、
備忘録的に記録しています。実際に動くソースコードを多用して説明していますので、
これからEclipseや、Spring-MVCを始めたいと思っている人にとって、少しでも参考になれば幸いです。
■SpringMVC の小径 ちょっと寄り道 ロギングの小径
9-4)AOP ロギングの魔法
ちょっと思い立って寄り道したロギングの小径ですが、そろそろ出口が見えてきたようです。
もう少し堪能したかったのですが仕方ありませんね。
それでは最後に、AOPによるロギングの魔法術を一つ披露してお別れすることにしましょう。

AOP(Aspect-Oriented Programming)とは?
私のへたくそな話術では、絶対理解してもらえないと自信を持って言えますので、
AOPについて説明しているサイトを一つ二つご紹介しておきます。
IT用語辞典
   うーむ。。なんか余計混乱してきた。
[ThinkIT] 第5回:AOPとは何か (1/4)
   引用:「AOPとはアスペクト指向に基づいたプログラミングのことです。」← そのまんまやんけ(笑)
まぁ、それだけ説明が難しいということにしておきましょう。

2002年終わりから2003年の頭ごろだったと思いますが、当時AspectJの出だしの頃には、
Aspect == 織り込み という解釈がありました(今でもそうなのかな??)
「織り込み」つまり、既に完成してきちんと動いているプログラムのソースコードに
まったく変更を加えることなく、後から透明な見えない糸を織り込むように、
プログラムに別の新しい振る舞いを加えてしまう。というまるで魔法のような実装方法のことを、
「アスペクト指向プログラミング」と私は呼んでいます。(ほかの人はどうか、それは知りません)

Springフレームワークには、このAspectJが進化した、Spring-AOPという優れたプラグインが存在します。
AOPを使うためには、aspectjweaverと、aspectjrtというプラグインを必要としますが、
pom.xmlには最初からこれを想定して定義してあるので、今回特になにも追加する必要はありません。
このプラグインを利用して、「9-3)log4j2 ログクラスの実装」までで(一応)完成しているプログラムのコードに
変更を加えることなく、ロギング魔法をかけてみます。乞うご期待。

でわ、まずはいきなり魔法の種明かしです。
src/main/java/jp/dip/arimodoki/common/LogAspect.java

クラスの最初に、@Aspectアノテーションという魔法の合言葉と
メソッドに、@Beforeとか、@Afterとか、@AfterThrowingというアノテーションの呪文を付け加えます。
@Beforeと、@Afterアノテーションが付いたメソッドの引数にある JoinPoint jp 引数は決まり文句なので、
この通りに書いとけば大丈夫です。

もうずいぶん前のことできっと忘れていると思いますが、
4-2)Spring-MVC設定」で、「applicationContext.xml」の設定で、
<!--AspectJ 使用宣言 -->
<aop:aspectj-autoproxy />
という設定を行いました。
この定義が、ここでAOPを有効にするという定義になります。

魔法の呪文はたったこれだけです。
でもせっかく作ったのに、このクラスのメソッドはどこからも呼び出されていないし、
これがいったいどうなるの?
それは、プログラムを動かしてみてのお楽しみです。
それでは、最後の最後の最後です。Aspectの魔法をかけたプログラムを動かしてみます。
プログラムは、「8-4)邂逅の頂」から何も触っていません。
ブラウザのURLに前と同じ「http://localhost:8080/j_Labo/promenade.xhtml」を入力してみます。

おやまたなんと奇っ怪な!!Eclipseの「コンソールビュー」にLog4j2のログが出力されました。
ログに出現している、setupBind()とか、dbProc()とかのメソッドには、当然一行たりとも
logger.log_info()は書き込んでいないのに、実行すると @Before、@Afterの魔法がかかって
ログに出現する様になります。
ここではすべて正常な処理しか実行されないので実感がありませんが、
エラーが発生した場合は、もっとすごいエラーが出力されますので、
自分でなにかエラーが発生するような条件を設定して確認してみるのも一興です。

例えば、 int x = 10 / 0; //(0除算 上等!)とかをね。

例外処理(Exception Handling)については少し思うところがあるので
そのうち、きちんと検証を行ってどこかでご紹介したいと思います。

最後に一つ注意点。@Aspectには一つ弱点があります。
アプリケーション内のクラスで定義されているメソッドのスコープが privateメソッドの場合には適用できません。
それ以前に、privateメソッドから、AOPのメソッド(@Before、@Atfet、@AfterThrowing)が呼び出された瞬間に、
摩訶不思議なNullPointerException あるいは、IllegalStateException等が発生します。
@Aspectアノテーションを有効にしたアプリケーションは、
publicスコープのメソッドしか使えないという問題を抱えています。
理由については、色々探しているのですが今のところ良く解りませんが、
とにかくpublicスコープ以外のメソッドはダメ!です。
私は最初、この制限が解らなくて道に迷い、崖から転落して這い上がるのに
半日かかったことがあるので皆さんもくれぐれもご用心を!
このソースコードでは、Aspect対象のプログラムを指定パッケージ階層配下すべてに対して適用していますが、
特定のクラスに絞ってAspect対象とするようなことも可能です。
このあたりの詳しい説明は、テックノートさん
とかに載っているので必要な時は、ここら辺をみて自分で調べてください。

アスペクト指向プログラミングのテクニックは、ロギング以外でも考えようによっては色々と、
あとから機能を追加できるという利点がありますが、
現実的には、非機能要件であるロギングなどには威力を発揮しますが、
最初から設計書で要件定義されているような機能に使うのはあまり好ましいとは言えません。
これをあまり多用しすぎると、プログラミングの処理の連続性が非常に見えにくくなってしまい、
デバッグの際に混乱してしまいます。
十分に注意して使用するようにしましょう。

 

ロギングの小径には、不思議な花が咲いていてとても興味深かったですね。
最初の予定ではこんなに長い散歩になるとは夢にも思いませんでしたが、
とりあえず怪我もなく、無事に幹線道路に戻ってこられてほっと一安心です。

まだまだ歩き足りない気がしないでもないですが、
あまり無理をすると、それこそ大怪我の元にもなりまねません。
ここでひとまず現地解散とします。
各自気を付けてお帰りください。
続きはまたそのうちに、次は今回とはまた違うルートを一緒に歩きたいと思います。