Edited at

spring AOPについて

Spring AOPについての個人的な備忘録です。

間違いがありましたらコメントいただけるとありがたいです。


参考

Spring 徹底入門


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());
}
}