Spring BootでAOP(アスペクト指向)を使うとコードが奇麗になる(@Aspect,@Before,@Afterなど)

Spring BootでAOP(アスペクト指向)を使うとコードが奇麗になる

オブジェクト指向にアスペクト指向も取り入れるとソースが奇麗になります。

アスペクト指向というのは私が新人の時の社内勉強会で勉強したのですが当時はチンプンカンプンでよくわかりませんでした。

「横断的」という言葉が特に意味が分かりませんでしたが、すごく簡単に言うとプログラムの至る所でしている本来あるべきでない処理を全て纏める。だから横断的(アスペクト)という言葉を使うんだと思います。

一番わかりやすいのは、メソッドの開始終了のログなどは本来メソッドにあるべき処理ではありません。

こういうのを削除して、AOP指向を取り入れてログの処理は一つのクラスだけに任せます。

Spring BootにはAOPが用意されており、build.gradleのdependenciesに以下を追記します。

空のコントローラを作成します。何もしていないメソッドを2つ用意しただけです。

AOPコンポーネントを作成します。

AOPのクラスには@Aspectアノテーションを付与します。各アノテーションの意味です。

アノテーション 意味
@Before メソッド前に実行する
@After メソッド後に実行する

これでメソッドの開始終了ログが出力されるようになります。

メインクラスは以下のようにしておきます。

このSpring Bootアプリケーションを実行すると以下のようにログ出力されます。

コントローラにあるメソッドは本来あるべき処理を記述するだけで、ログ出力はAOPコンポーネントに任せるというように実装します。

これによって本来あるべきコーディングと本来ないべきコーディングを分離することができます。

JoinPointクラス

@Beforeや@Afterがついたメソッドは引数にJoinPointクラスを持ちます。

色々出来るのですが簡単に以下にいくつか紹介しておきます。jpはJoinPointのインスタンスです。

取得値 メソッド
クラス名を取得 jp.getSignature().getDeclaringType().getSimpleName()
メソッド名を取得 jp.getSignature().getName()
引数名を取得 jp.getSignature()).getParameterNames()
引数の値を取得 jp.getArgs()

ServletUriComponentsBuilderからURI取得

org.springframework.web.servlet.support.ServletUriComponentsBuilderクラスからURIを取得することが出来ます。

log.info(ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString());

view raw
Aop.java
hosted with ❤ by GitHub

RequestContextHolderからHTTPメソッドを取得

org.springframework.web.context.request.RequestContextHolderクラスからHTTPメソッドを取得することが出来ます。

HttpServletRequest httpServletRequest =
((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
var httpMethod = httpServletRequest.getMethod();
log.info("{}",httpMethod);

view raw
Aop.java
hosted with ❤ by GitHub

ヘッダ情報を取得

ヘッダ情報も取得することが出来ます。

String[] argsNames = ((CodeSignature) jp.getSignature()).getParameterNames();

String配列に@RequestHeader HttpHeadersクラスの変数名が入ります。

@RequestMapping(path = "/test/{hoge}", method = RequestMethod.GET)
public void test(@PathVariable("hoge") String hoge, @RequestHeader HttpHeaders headers) {

view raw
Aop.java
hosted with ❤ by GitHub

このRestControllerの例ですと、argsNames = [hoge, headers]という順で取得できます。

同様にjp.getArgs()にも同じ順でObject[]として値が入ります。HttpHeadersは各ヘッダがLinkedHashMapのkey-valueで保持されています。

API Gateway経由でRestControllerを実行する際にContent-Typeがapplication/jsonではない場合、JSONスキーマでのバリデーションが効きません。その為、RestController(java)側でContent-TypeやHTTPメソッドを判断し、application/jsonではない場合はBAD REQUEST(400)にするなど、エラーハンドリングが必要になります。

@Validate,@Validが効かない

RestControllerでクエリパラメータの正規表現チェックをしようとしたのですが、@ArroundアノテーションでAOPしていると、@RestControllerAdviceアノテーションのエラーハンドリングが効かないです。

https://stackoverflow.com/questions/60890319/exception-in-spring-aop-itself-not-getting-handled-through-restcontrolleradvice

  • このエントリーをはてなブックマークに追加
  • Evernoteに保存Evernoteに保存

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA