[TIL] 23.07.09 Spring AOP 적용 , 실행시간 측정

hyewon jeong·2023년 7월 9일
1

TIL

목록 보기
137/138

Spring AOP 적용 방법

1. build.gradle 설정

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

2. Application 클래스에 추가

@EnableAspectJAutoProxy//aop 적용
@EnableJpaAuditing //auditing 기능 위한 추가
@SpringBootApplication
@EnableCaching // 레디스 캐싱 하기위해 추가, @Cacheable 같은 어노테이션을 인식 하게 함
public class WonyShopApplication {

  public static void main(String[] args) {
    SpringApplication.run(WonyShopApplication.class, args);
  }

}
@EnableAspectJAutoProxy//aop 적용

3. 실행시간 측정 Timer 어노테이션 정의

@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE} )
// 다른 메서드나 어노테이에 적용할수 있도록 대상을 지정하는 어노테이션
@Retention(RetentionPolicy.RUNTIME)
//어노테이션의 정보 유지 범위를 지정 어노테이션으로 런타임 시점까지 유지한다라는 뜻
public @interface Timer { //Timer 라는 어노테이션 정의

}

4. 실행측정 AOP 클래스

package study.wonyshop.aop;

import lombok.extern.slf4j.Slf4j;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

@Slf4j
@Aspect //여러객체에 공통으로 적용되는 기능을 제공하는 클리스 지정
@Component
public class ExecutionTimer {

  @Pointcut("@annotation(study.wonyshop.aop.Timer)") //Joinpoint의 부분 집합, 실제 Advice가 적용되는 Joinpoint를 나타냄
  private void timer(){}

    // 패키지의 Controller 라는 이름으로 끝나는 패키지에 모두 적용 (매서드만)
    @Pointcut("within(*..*Controller)")
    private void cut(){}
    // 메서드 전 후로 시간 측정 시작하고 멈추려면 Before,
    // AfterReturning으로는 시간을 공유 할 수가 없음 Around 사용!


//⭐️ Around Advice: 대상 메서드의 실행 전과 후 모두 실행됩니다. 대상 메서드를 직접 호출하는 것과 비슷하게 작동하며,
// 대상 메서드를 실행하는 ProceedingJoinPoint 객체를 파라미터로 전달받아 직접 실행 결정을 할 수 있다.
// Advice가 대상 메서드의 실행을 제어할 수 있다.



  //proceedingJoinPoint 메서드?
  //Advice가 적용될 지점은 Join Point(조인 포인트)라고 부르며, Join Point의 실행을 계속 진행하기 위한 메서드를 "proceedingJointPoint"라고 합니다.
  //즉 Advice가 적용된 메서드의 실행을 계속해서 진행하기 위한 지점을 가리키는 용어이다.
    @Around("timer()")// timer() 포인트컷을 사용하여 해당 어노테이션이 적용된 메서드의 실행 전후에 코드를 수행하도록 합니다.
   public Object AssumeExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {

        StopWatch stopWatch = new StopWatch();

        stopWatch.start();
        Object proceed = joinPoint.proceed();
        // 매서드를 실행시, 프록시 객체가 아닌 실제 대상 객체의 메서드 호출 한다.
         // 그래서 이 코드 전후로 공통기능을 위한 코드를 위치 시켜야한다.

        stopWatch.stop();

        long totalTimeMillis = stopWatch.getTotalTimeMillis();

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 현재 실행 중인 조인 포인트의 시그니처(메서드의 정보)를 가져옵니다.
      // joinPoint 객체는 현재 실행 중인 메서드에 대한 정보를 제공하는 객체입니다.


      String methodName = signature.getMethod().getName();
      //getMethod().getName()은 시그니처를 통해 메서드의 이름을 추출하는 메서드입니다.
      // signature.getMethod()을 호출하여 메서드 객체를 가져온 다음 getName()을 호출하여 메서드의 이름을 문자열로 얻을 수 있습니다.

        log.info("실행 메서드: {}, 실행시간 = {}ms", methodName, totalTimeMillis);
        return proceed;
    }
}

profile
개발자꿈나무

1개의 댓글

comment-user-thumbnail
2023년 7월 11일

멋집니다! 어디서 많이 본듯한 느낌이 듭니다..ㅋㅋㅋㅋ

답글 달기