Spring, Spring Boot/AOP

AOP Spring Boot에서 사용하기

너지살 2023. 8. 17. 00:06

 

 

순서

AOP를 Spring Boot에서 실행하기 위해 다음의 단계들을 거칩니다.

  1. 의존성 추가
  2. Application에 Annotation 추가
  3. Aspect 파일 생성 
  4. 메소드 생성
    1. 실행 범위 지정
    2. 실행 코드 구현 

 

 

 

의존성 추가

implementation 'org.springframework.boot:spring-boot-starter-aop'

 

 

 

Application에 Annotation 추가 

@EnableAspectJAutoProxy 이 어노테이션을 어플리케이션 클래스에 추가합니다. 

@SpringBootApplication
@EnableAspectJAutoProxy // aop 사용
public class UserApplication {
	public static void main(String[] args) {
		SpringApplication.run(UserApplication.class, args);
	}
}

 

 

 

파일 생성

저 같은 경우는 aop 패키지를 생성하고 LoggingAspect.java 클래스 파일을 생성해 작업을 했습니다. 

 

  • @Aspect, @Component, @Slf4j 어노테이션 추가 
  • AOP 메소드 생성 

 

 

 

전체 코드

package com.dotd.user.aop;


import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Slf4j
public class LoggingAspect {

    // Before : 메소드 실행 전
    @Before("execution(* com.dotd.user.controller..*(..))")
    public void logBefore(JoinPoint joinPoint) {
        log.info("Before 실행 : {}", joinPoint.getSignature().toShortString() );
    }

    // After : 메소드 실행 후
    @After("execution(* com.dotd.user.controller..*(..))")
    public void logAfter(JoinPoint joinPoint) {
        log.info("After 실행 : {}", joinPoint.getSignature().toShortString() );
    }

    // AfterReturning : 메소드가 실행하고 반환된 후 실행
    // returning 은 결과값을 받을 객체를 선택
    @AfterReturning(value = "execution(* com.dotd.user.controller..*(..))", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        log.info("AfterReturning 실행 : {} + 결과 : {}", joinPoint.getSignature().toShortString(), result);
    }

    // AfterThrowing : 메소드에 예외가 발생했을 때 실행
    // throwing 은 예외값을 받을 객체를 선택
    @AfterThrowing(pointcut = "execution(* com.dotd.user.controller..*(..))", throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
        log.info("AfterThrowing 실행 : {} + 예외 : {}", joinPoint.getSignature().toShortString(), e);
    }


    // Around :  실행 전, 후
    @Around("execution(* com.dotd.user.controller..*(..))")
    public Object logAroundControllerMethods(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        log.info("Around 시작 : {}", joinPoint.getSignature().toShortString());

		// 실제 메서드 실행
		// 이 코드를 기준으로 전, 후가 나누어짐
        Object result = joinPoint.proceed();  

        long elapsedTime = System.currentTimeMillis() - startTime;
        log.info("Around 끝 : {} / 걸린 시간 :  {} ms", joinPoint.getSignature().toShortString(), elapsedTime);
        return result;
    }
}

 

 

메소드 

    @Before("execution(* com.dotd.user.controller..*(..))")
    public void logBefore(JoinPoint joinPoint) {
        log.info("Before 실행 : {}", joinPoint.getSignature().toShortString() );
    }

메소드의 각각 요소들에 대해 알아보겠습니다.

 

 

    @Before("execution(* com.dotd.user.controller..*(..))")
  • @Before : @뒤에 AOP메소드의 실행 지점을 설정합니다. (After, AfterReturning, Around .. )
  • "execution(* com.dotd.user.controller..*(..))" 은 AOP를 적용할 대상을 뜻 합니다. 
  • 여기서는 com.dotd.user.controller 의 패키지와 하위 패키지에 적용합니다. 

 

 

public void logBefore(JoinPoint joinPoint) {
    log.info("Before 실행 : {}", joinPoint.getSignature().toShortString() );
}
  • JoinPoint joinPoint 은 프로그램 실행 중에 특정 위치를 말합니다. 즉, Advice(AOP의 코드)를 삽입할 수 있는 프로그램의 특정 지점을 의미합니다. 
  • joinPoint.getSignature().toShortString() : join point에 대해 짧은 문자열로 반환 

 

 

 

 

실행 시점

AOP 실행 순서

 

Around 전 -> Before -> 로직 -> AfterReturning -> After -> Around 후

이 순서로 실행되는 것을 볼 수 있습니다.