スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Spring MVC AspectJを使ったAOPの検証

前回・前々回とFilterの検証を行ったため、今回はある処理を挟み込むという点で似た機能を提供しているAOPについて検証することにした。
良い機会なので、作成したFilterも今回の検証に使用し、どのような処理順になるかも確認してみる。

■Filterに関する記事
Spring MVCとFilterを使ってみる
Spring MVCとFilterを使ってみる(その2)

◎動作検証にあたっての各バージョンは以下の通り
  • SpringFramework 3.2.3.RELEASE
  • Java 1.7
  • Tomcat 7.0

1.Mavenのpom.xml


org.aspectj
aspectjweaver
1.8.4


2015年1月26日時点で最新のaspectjweaverを使用した。
なお、spring-aopも必要であるが、spring-webmvcに依存しているため、ここでは別途追加しない。

2.mvc-config.xml


<aop:aspectj-autoproxy/>

SpringでAspectJのAOPを使用する場合は、こちらの設定を1行追加する。
追加しない場合、AOPが有効とならない。

3.AspectJを使用したクラス


package jp.co.sample.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LogAspect{

private static Logger logger;

// 下記のコメントアウトも書き方もすべてOK
// @Around("execution(public String jp.co.sample.book.controller.BookController.create(..))")
// @Around("execution(String jp.co.sample.book.controller.BookController.create(..))")
// @Around("execution(String *..create(..))")
// @Around("execution(String create(..))")
@Around("execution(* create(..))")
public String aroundCreate(ProceedingJoinPoint joinPoint) throws Throwable {

logger = LoggerFactory.getLogger(joinPoint.getThis().getClass());

logger.info("create start");
String result = (String) joinPoint.proceed();
logger.info("create end");
return result;
}
}

説明の前に、AOPでよくでてくるキーワードについて簡単に補足しておく。
Aspect(アスペクト)・・・AdviceとPointcutをまとめたもの
Advice(アドバイス)・・・Joinpontで実行される処理(Adviceのタイプには「Around Advice」や「Before Advice」等用意されている)
Joinpont(ジョインポイント)・・・メソッドの呼び出しや例外発生のポイント
Pointcut(ポイントカット)・・・複数のJoinpointをまとめたもの

AdviceのタイプはJoinpointの前後で実行される@Aroundアノテーションを使用することにより、String result = (String) joinPoint.proceed();の前後に挟み込みたい処理を適用できる。今回は、メソッドの開始・終了ログを出力する処理を追加した。
Pointcutを@Aroundアノテーションの引数に記載するのだが、書き方が難しいと感じたので、参考までに動作確認できた他のパターンも載せておく。補足説明しておくと、publicやprivateなどは省略可能、パッケージとクラス名も省略可能で、「*」はドットを含まない任意の文字列、「.. 」はドットを含む任意の文字列となる。
また、メソッド名を「aroundCreate」としているが、こちらは任意である。ただし、@Aroundアノテーションの場合、パラメタに「ProceedingJoinPoint」を使用する必要がある。戻り値については、AOP対象メソッドの戻り値の型と互換性が必要で、サンプルの場合、AOP対象のcreateメソッドは画面名を返すためString型としている。
なお、mvc-config.xmlにコンポーネントスキャンを定義しているので、@Componentクラスアノテーションを使用してDIの対象としている。

4.動作確認


INFO EncodingFilter#doFilter - doFilter start
INFO LogFilter#doFilter - doFilter start
INFO BookController$$EnhancerByCGLIB$$a98d96da#aroundCreate - create start
INFO BookController#create - create start
INFO BookController$$EnhancerByCGLIB$$a98d96da#aroundCreate - create end
INFO LogFilter#doFilter - doFilter end
INFO EncodingFilter#doFilter - doFilter end

実行した結果、Filterが先に動作し、AOPが適用されていることが確認できた。(※「BookController#create - create end」は用意していない。)

◎まとめ
Bean定義ファイルに<aop:aspectj-autoproxy/>を記載するだけで、あとは@Aspectや@Aroundアノテーションを使う方法は、非常に分かりやすく感じた。また、@Componentでインジェクションできる点も良い。
今までSpring AOPとAspectJの棲み分けがよく分かっていなかったが、今回の検証で理解することができた。
また、今回Filter、AOPともにログ出力処理を対象メソッドの前後に挟み込んだが、URLベースのFilterとメソッドベースのAOPという明確な違いを認識できた点でも、検証した甲斐があったと思う。

■過去のSpring関連記事
Spring関連記事 Index

スポンサーサイト

コメントの投稿

非公開コメント

プロフィール

bookmount8

Author:bookmount8
システムエンジニア。サーバーサイドでjavaを扱うことが多い。最近は、ミドルやフロント周りも関心あり。

最新記事
カテゴリ
検索フォーム
最新コメント
月別アーカイブ
これまでの訪問者数
ブロとも申請フォーム

この人とブロともになる

RSSリンクの表示
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。