Spring

스프링 AOP 실제 프로젝트 적용

쭈녁 2024. 1. 18. 18:11

 

 

AOP 예제

 

@Aspect
@Slf4j
public class CallLogAspect {
    @Before("execution(* hello.aop.internalcall..*.*(..))")
    public void log(JoinPoint joinPoint) {
        log.info("aop={}", joinPoint.getSignature());
    }
}

 

 

특정 경로 값 하위에 AOP를 적용하도록 하는 예제이다.

하지만 실제로 사용할 때에는 재사용성이 떨어진다.

따라서 특정 경로(특정 클래스 전체 or 특정 패키지 하위)에 적용 할 때는 위의 방법을 활용하고

메서드 단위에서 PointCut의 재사용성을 높이기 위해서는 커스텀 어노테이션을 활용한다.

 

 

어노테이션 방식 적용

 

 

커스텀 어노테이션

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
}

 

 

어드바이저

@Slf4j
@Aspect
@Component
public class MyLogAspect {
    @Around("@annotation(myLog)")
    public Object log(ProceedingJoinPoint joinPoint, MyLog myLog) throws Throwable {
        log.info("AOP 시작");
        long start = System.currentTimeMillis();
        try {
            log.info("실행 메서드 = {}", joinPoint.getSignature());
            return joinPoint.proceed();

        } catch (Exception e) {
            log.info("예외 발생 = {}", e.getMessage());
            throw e;
        } finally {
            long end = System.currentTimeMillis();
            log.info("소요 시간 = {}ms", end - start);
            log.info("AOP 끝");
        }
    }
}

 

인자에 MyLog 타입의 어노테이션을 받아오는 형식으로 작성하고

PointCut은 @Around("@annotation(myLog)") 어노테이션 이름으로 지정한다.

이렇게 설정하면 해당 어노테이션이 붙은 메서드에 AOP를 적용 할 수 있다.

 

 

컨트롤러단에서 AOP 적용

@MyLog
@PostMapping("/create")
public String createPost(@RequestParam(name = "category") String category
        , @Valid PostCreateDto postCreateDto
        , RedirectAttributes redirectAttributes
        , @AuthenticationPrincipal PrincipalDetail principalDetail) {

    postCreateDto.setUrlAddress(category);
    postCreateDto.setUserId(principalDetail.getId());

    PostResponseDto postResponseDto = postService.savePost(postCreateDto);
    redirectAttributes.addAttribute("postId", postResponseDto.getId());
    return "redirect:detail/{postId}";
}

 

 

AOP 로그