스프링 AOP 실전 예제
예제 만들기
@Repository
public class ExamRepository {
private static int seq = 0;
/**
* 5번에 1번 실패하는 요청
*/
public String save(String itemId) {
seq++;
if (seq % 5 == 0) {
throw new IllegalStateException("예외 발생");
}
return "ok";
}
}
- Repository 예제
- save()에서 요청이 5번 중 1번 예외 발생으로 실패한다.
@Service
@RequiredArgsConstructor
public class ExamService {
private final ExamRepository examRepository;
public void request(String itemId) {
examRepository.save(itemId);
}
}
- Service 예제
로그 출력 AOP
- 목표 - @Trace 어노테이션이 메소드에 붙어있으면 호출 정보가 출력되도록 한다.
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Trace {
}
- @Trace 사용자 정의 어노테이션 클래스 생성
@Aspect
@Slf4j
public class TraceAspect {
@Before("@annotation(hello.aop.exam.annotation.Trace)")
public void doTrace(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
log.info("[trace] {} args={}", joinPoint.getSignature(), args);
}
}
- @Trace 어노테이션을 사용하는 메소드에 적용할 Aspect
- @Trace는 메소드 단위에 붙는 어노테이션이기에 포인트컷을 @annotation으로 지정
- doTrace() 어드바이스
- 조인 포인트 시그니처와 인수등 호출 정보를 출력해준다.
@Service
@RequiredArgsConstructor
public class ExamService {
private final ExamRepository examRepository;
@Trace
public void request(String itemId) {...}
}
@Repository
public class ExamRepository {
private static int seq = 0;
/**
* 5번에 1번 실패하는 요청
*/
@Trace
public String save(String itemId) {...}
}
- @Trace 적용
- Repsoitory의 save()와 Service의 request()에 @Trace 어노테이션 사용
- TraceAspect의 포인트컷 대상에 일치하므로 프록시가 생성되고 어드바이스가 적용된다.
- Repsoitory의 save()와 Service의 request()에 @Trace 어노테이션 사용
재시도 AOP
- 목표 - @Retry 어노테이션이 있으면 예외 발생 시 다시 시도해서 문제를 복구하도록 한다.
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Retry {
int value() default 3;
}
- @Retry 사용자 어노테이션 클래스 생성
- 별도의 값을 지정하지 않으면 기본값을 3으로 설정한다.
@Aspect
@Slf4j
public class RetryAspect {
@Around("@annotation(retry)") //Retry 전체 패키지 경로를 명시하지 않아도 파라미터에 명시한 Retry 타입 정보를 대입해준다.
public Object doRetry(ProceedingJoinPoint joinPoint, Retry retry) throws Throwable {
log.info("[retry] {} retry={}", joinPoint.getSignature(), retry);
int maxRetry = retry.value();
Exception exceptionHolder = null;
for (int retryCount = 1; retryCount <= maxRetry; retryCount++) {
try {
log.info("[retry] try count={}/{}", retryCount, maxRetry);
return joinPoint.proceed();
} catch (Exception e) {
exceptionHolder = e;
}
}
//재시도 횟수가 넘어가면 예외를 던지도록 설정
throw exceptionHolder;
}
}
- @Retry 어노테이션을 사용하는 메소드에 적용할 Aspect
- @Retry는 메소드 단위에 붙는 어노테이션이기에 포인트컷을 @annotation으로 지정
- doRetry() 어드바이스
- 예외 발생 시 재시도하는 Aspect이다.
- @annotation(retry)는 별도의 전체 패키지명을 명시하지 않아도 파라미터에 명시한 Retry retry의 타입 정보를 가져와서 사용한다.
- retry.value()를 통해서 어노테이션에 지정한 값(3)을 가져올 수 있다.
- for 루프를 통해서 예외가 발생해서 결과를 정상 반환하지 않는 경우 retry.value() 값 만큼 재시도를 하고 재시도 횟수가 넘어가는 경우 마지막 예외를 저장해뒀다가 던진다.
- 이런 기능의 경우 재시도 횟수 제한을 필수로 해줘야한다.
@Repository
public class ExamRepository {
private static int seq = 0;
/**
* 5번에 1번 실패하는 요청
*/
@Trace
@Retry(4) //value = 4로 설정
public String save(String itemId) {...}
}
- Repository에 @Retry 어노테이션 사용
- @Retry에 값을 지정해주지 않으면 기본 값인 3으로 설정된다.
출처 : [인프런 김영한 스프링 핵심 원리 - 고급편]
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B3%A0%EA%B8%89%ED%8E%B8/dashboard
스프링 핵심 원리 - 고급편 강의 | 김영한 - 인프런
김영한 | 스프링의 핵심 원리와 고급 기술들을 깊이있게 학습하고, 스프링을 자신있게 사용할 수 있습니다., 핵심 디자인 패턴, 쓰레드 로컬, 스프링 AOP스프링의 3가지 핵심 고급 개념 이해하기
www.inflearn.com
'Spring > [인프런 김영한 스프링 핵심 원리 - 고급편]' 카테고리의 다른 글
[인프런 김영한 스프링 핵심 원리 - 고급편] 스프링 AOP - 실무 주의사항 (2) | 2024.12.27 |
---|---|
[인프런 김영한 스프링 핵심 원리 - 고급편] 스프링 AOP - 포인트컷 (0) | 2024.12.27 |
[인프런 김영한 스프링 핵심 원리 - 고급편] 스프링 AOP 구현 (0) | 2024.12.17 |
[인프런 김영한 스프링 핵심 원리 - 고급편] 스프링 AOP 개념 (0) | 2024.12.16 |
[인프런 김영한 스프링 핵심 원리 - 고급편] @Aspect AOP (0) | 2024.12.15 |