AOP는 Aspect Oriented Programming 의 약자로 관점 지향 프로그래밍이라고 한다.
OOP를 설계 할 때 각각의 함수 또는 모듈마다 트랜잭션, 보안, 시간재기, 로깅과 같은 것을 다 써놓았는데 이것들을 모듈화 시키는 개념이다.
@Target(ElementType.METHOD)
public @interface RunningTime {
}
위 코드처럼 어노테이션을 만들 수 있다.
@Target() : 어노테이션 적용대상을 설정@Aspect
@Component
@Slf4j
public class DebuggingAspect {
@Pointcut("@annotation(com.example.shoppingmall.aop.annotation.RunningTime)")
private void enableRunningTime(){}
@Pointcut("execution(* com.example.shoppingmall.api.*.*(..))")
private void controllerPointcut(){}
@Around("enableRunningTime()")
public Object loggingRunningTime(ProceedingJoinPoint joinPoint) throws Throwable{
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object returningObh = joinPoint.proceed();
stopWatch.stop();
String methodName = joinPoint.getSignature().getName();
log.info("'{}' total running time : {} sec", methodName, stopWatch.getTotalTimeSeconds());
return returningObh;
}
@Around("controllerPointcut()")
public Object loggingRunningTimeController(ProceedingJoinPoint joinPoint) throws Throwable{
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
StopWatch stopWatch = new StopWatch();
Map<String, Object> params = new HashMap<>();
stopWatch.start();
Object returningObh = joinPoint.proceed();
stopWatch.stop();
String methodName = joinPoint.getSignature().getName();
try {
params.put("method", joinPoint.getSignature().getName());
params.put("logTime", LocalDateTime.now().withNano(0));
params.put("requestURI", request.getRequestURI());
params.put("http_method", request.getMethod());
} catch (Exception e) {
log.error("LoggerAspect error", e);
}
log.info("{}", params);
log.info("'{}' total running time : {} sec\\n\\n", methodName, stopWatch.getTotalTimeSeconds());
return returningObh;
}
}
loggingRunningTime() : @RunningTime을 원하는 메서드에 붙이면 작동하게 설계
loggingRunningTimeController() : 모든 Controller를 대상으로 작동하게 설계
처음엔 필요한 함수에 어노테이션을 붙여 사용하도록 만들었었는데 완성도가 높아질수록 각 요청마다 어노테이션이 필요하게되어 최종적으로는 모든 Controller를 대상으로하여 설정
@Around() : 조건을 만족하는 대상 메서드 실행 전 후 모두 동작
위의 코드처럼 어려운건 없지만 주의할 점은 있다.
AOP 기능을 원하는 메서드가 Return Object가 존재한다면 해당 AOP 메서드에서도 꼭 return returningObh 와 같이 return 해주어야한다.