Spring AOPについての個人的な備忘録です。
参考
Spring 徹底入門
【Spring】Spring AOPについて
Spring AOP
JoinPoint(指定したメソッドの実行前や実行後などのタイミング)に対して、@Aspectアノテーションを付与したクラスで実装した処理を差し込めます。
使用可能なAdviceのアノテーション
アノテーション | 説明 |
---|---|
@Before | 対象のメソッドの実行前に処理が差し込まれる。 |
@AfterReturning | 対象のメソッドが正常終了した後に処理が差し込まれる。正常終了時のメソッドの戻り値を取得することもできる。 |
@AfterThrowing | 対象のメソッドが異常終了(例外がスローされたとき)に処理が差し込まれる。異常終了時の例外を取得することもできる。 |
@After | 対象のメソッドが正常終了や例外のスローに関わらず、終了時に処理が差し込まれる。 |
@Around | 最も強いAdvice。対象のメソッドの前後に処理が差し込まれる。 |
実装
Before
SampleAspect.java
package com.example.demo;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class SampleAspect {
@Before("execution(public * com.example.demo.controller.*.*(..))")
public void startLog(JoinPoint jp) {
System.out.println("メソッド開始:" + jp.getSignature());
}
}
After Returning
SampleAspect.java
package com.example.demo;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import com.example.demo.controller.resorces.UserResponse;
@Aspect
@Component
public class SampleAspect {
@AfterReturning(value = "execution(public * com.example.demo.controller.*.*(..))", returning = "user")
public void endLog(JoinPoint jp, UserResponse user) {
System.out.println("メソッド正常終了:" + jp.getSignature());
System.out.println("戻り値:" + user);
}
}
After Throwing
SampleAspect.java
package com.example.demo;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class SampleAspect {
@AfterThrowing(value = "execution(public * com.example.demo.controller.*.*(..))", throwing = "e")
public void endLog(JoinPoint jp, RuntimeException e) {
System.out.println("メソッド異常終了:" + jp.getSignature());
e.printStackTrace();
}
}
After
SampleAspect.java
package com.example.demo;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class SampleAspect {
@After("execution(public * com.example.demo.controller.*.*(..))")
public void endLog(JoinPoint jp) {
System.out.println("メソッド終了:" + jp.getSignature());
}
}
Around
SampleAspect.java
package com.example.demo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class SampleAspect {
@Around("execution(public * com.example.demo.controller.*.*(..))")
public Object log(ProceedingJoinPoint jp) throws Throwable {
System.out.println("メソッド開始:" + jp.getSignature());
Object result;
try {
// 対象メソッド実行
result = jp.proceed();
System.out.println("メソッド終了:" + jp.getSignature());
System.out.println("戻り値:" + result);
return result;
} catch (Throwable e) {
System.out.println("メソッド異常終了:" + jp.getSignature());
e.printStackTrace();
throw e;
}
}
}
Pointcut
名前付きPointcut
pointcutに名前を付けて再利用することもできます。
SampleAspect.java
package com.example.demo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class SampleAspect {
@Pointcut("execution(public * com.example.demo.controller.*.*(..))")
public void demoController() {}
@Before("demoController()")
public void startLog(JoinPoint jp) {
System.out.println("メソッド開始:" + jp.getSignature());
}
}