暇な日々にスパイスを

学んだ技術の備忘録

Spring Boot 4 AOPでLog出し

Webアプリケーションの開発と保守を行う場合、リクエストとレスポンスの詳細が出ている方が良いと考えています。
AOPを利用して、メソッドのinとoutを出力させていきます。

以下の記事を参考にしました。
はじめてのSpring AOP - CLOVER

AOPについては以下の記事を参考にしています。
7.2 @AspectJ support - minokubaの日記

設定

  1. build.gradleに追加します
    f:id:snona:20160211225429p:plain
    以下を追加します。
compile('org.springframework.boot:spring-boot-starter-aop')
  1. Gradle Refresh All
  2. application.ymlにログ設定の追加 f:id:snona:20160211225809p:plain
    TodoAppフォルダのTodo.logが出力先です。
    自作のクラスに対してdebugレベルで出力させます。

ソースコードの追加

ログが出ていることを確認するために、適当なコードを追加します。

  1. com/todo/service/SampleService.javaの作成
    f:id:snona:20160211225815p:plain
    足し算をするサービスを提供します。
package com.todo.service;

import org.springframework.stereotype.Service;

@Service
public class SampleService {
  public int add(int a, int b) {
    System.out.println("#add" + " called.");
    return a + b;
  }
}
  1. com/todo/restcontroller/SampleRestController.javaの作成
    f:id:snona:20160211230034p:plain
    localhost:8080/にアクセスされた際に、画面に"Add 1 + 2 =" 上記サービスの足し算結果を表示します。
package com.todo.restcontroller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.todo.service.SampleService;

@RestController
public class SampleRestController {
  @Autowired
  SampleService sampleService;

  @RequestMapping("/")
  public String home() {
    return "Add 1 + 2 =" + sampleService.add(1, 2);
  }
}

@Autowiredで上記のSampleServiceをDIにより埋め込んでいます。 0. AOPによる挟み込み処理 f:id:snona:20160211230635p:plain

package com.todo;

import java.util.Arrays;

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 TraceInterceptor {
  protected Logger logger = LoggerFactory.getLogger(getClass());

  @Around("execution(* com.todo..*.*(..))")
  public Object invoke(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    Object ret = null;
    try {
      logger.debug("before invoke, parameters = " + Arrays.toString(proceedingJoinPoint.getArgs())
          + ", by " + proceedingJoinPoint.getTarget().getClass() + "#"
          + proceedingJoinPoint.getSignature().getName());

      ret = proceedingJoinPoint.proceed();
      return ret;
    } finally {
      logger
          .debug("after invoke, result = " + ret + ", " + proceedingJoinPoint.getTarget().getClass()
              + "#" + proceedingJoinPoint.getSignature().getName());
    }
  }
}

@Aspectと@Componentを付けます。
AspectJの設定は上記記事を参考にしてください。
ここでは、@Aroundで処理前と処理後にログへの書き出しをしています。
範囲は、"execution( com.todo...*(..))"でcom.todo配下のパッケージに含まれるメソッド(引数は問わない)です。

実行結果

  1. 起動させた後に、RestControllerを叩きます。
    f:id:snona:20160211230903p:plain
  2. ログを確認します。
    f:id:snona:20160211230922p:plain
    各処理への入力と出力がログへ書きだされていることがわかります。

これで更に開発がしやすくなったのではないでしょうか。 そろそろ画面に移っていきたいですね。