

메서드가 실행된 시간을 측정하는 예제
public ResponseEntity<UserResponse> signInCon(@Parameter @RequestBody UserSignInRequest userSignInRequest) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    try {
        return ResponseEntity.ok(userService.signIn(userSignInRequest));
    }finally {
        stopWatch.stop();
        log.info("user sign in {} ms", stopWatch.getLastTaskTimeMillis());
    }
}

@Component
@Aspect
@Slf4j
public class Performance {
    @Around("execution(* com.semobook..*.UserController.*(..))")
    public Object calculatePerformanceTime(ProceedingJoinPoint proceedingJoinPoint) {
        Object result = null;
        try {
            long start = System.currentTimeMillis();
            result = proceedingJoinPoint.proceed();
            long end = System.currentTimeMillis();
            log.info("{} ms", end - start);
        } catch (Throwable throwable) {
            log.info("Exception");
            throwable.printStackTrace();
        }
        return result;
    }
}
@Aspect어노테이션을 붙여 Aspect를 나타내는 클래스라는 겻을 명시하고 @Component를 사용해 스프링 빈에 등록.
@Around어노테이션은 타겟 메서드를 감싸서 특정 Advice를 실행한다는 의미이며, @Around("execution(* com.semobook..*.UserController.*(..))")는 com.semobook 아래의 패키지 경로의 UserController객체의 모든 메서드에 이 Aspect를 정용한다는 의미.
@Around : 어드바이스
execution : 포인트컷 지정자
*리턴타입을 나타냄, 위코드에서는 모든 타입 리턴 가능
com.semobook..*.UserController.* : 타겟이 되는 메소드 지정
(..) : 인자(agument)타입, 위코드에서는 모든 타입 인자 허용
어드바이스
@Before : 어드바이스 타겟 메소드가 호출되기 전에 어드바이스 기능을 수행@After: 타겟 메소드의 결과에 관계없이(성공, 예외 관게 없음) 타겟 메소드가 완료 되면 어드바이스 기능을 수행@AfterReturning:타겟 메소드가 성곡적으로 결과값을 반환 후에 어드바이스 기능을 수행@AfterThrowing: 타겟 메소드가 수행 중 예외를 던지게 되면 어드바이스 기능을 수행@Around: 어드바이스가 타겟 메소드를 감싸서 타겟 메소드 흐름전과 후에 어드바이스 기능을 수행@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface PerformanceCheck {
}
@Component
@Aspect
@Slf4j
public class PerformanceAspect {
//    @Around("execution(* com.semobook..*.UserController.*(..))")
    @Around("@annotation(com.semobook.tools.PerformanceCheck)")
    public Object calculatePerformanceTime(ProceedingJoinPoint proceedingJoinPoint) {
        Object result = null;
        try {
            long start = System.currentTimeMillis();
            result = proceedingJoinPoint.proceed();
            long end = System.currentTimeMillis();
            log.info("{} ms", end - start);
        } catch (Throwable throwable) {
            log.info("Exception");
            throwable.printStackTrace();
        }
        return result;
    }
}
execution expression을 "@annotation(com.semobook.tools.PerformanceCheck)"로 대체
/**
 * userId로 회원조회
 **/
@PerformanceCheck
public UserInfoDto findByUserId(String userId) {
  	UserInfoDto userInfoDto = new UserInfoDto(userRepository.findByUserId(userId));
    return userInfoDto;
}
https://engkimbs.tistory.com/746
https://jojoldu.tistory.com/71