공통 관심 사항과 핵심 관심 사항을 분리하기 위해 AOP를 적용할 수 있다.
AOP 객체 생성 후 빈을 등록해줘야하는데
1. 컴포넌트 스캔
2. 자바 코드로 직접 스프링 빈 등록
두 가지 방법 모두 가능하다.
package hello.hellospringdemo.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component // bean 등록
@Aspect // AOP
public class TimeTraceAop {
// 공통 관심사항 적용 타겟팅
@Around("execution(* hello.hellospringdemo..*(..))") // 하위 패키지에 모두 적용 가능
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
System.out.println("START: " + joinPoint.toString());
try {
return joinPoint.proceed();
} finally {
long finish = System.currentTimeMillis();
long timeMs = finish - start;
System.out.println("END: " + joinPoint.toString() + " " + timeMs + "ms");
}
}
}
@Bean
public TimeTraceAop timeTraceAop() {
return new TimeTraceAop();
}
강의에서 컴포넌트 스캔 방식을 다루어서 나는 직접 스프링 빈을 등록해보았다. 그런데 다음과 같은 오류가 뜨면서 종료되었다.
찾아보니까 순환 참조 문제였다. 그럼 어떻게 해결하느냐,,! 궁금해서 찾아보니까 @Around에 메인 메서드가 존재하는 애플리케이션을 포함하여 하위 패키지에 적용하도록 되어 있어서 timeTraceAop() 메소드 호출 시 자기 자신인 TimeTraceAop를 생성해서 순환 참조 문제가 발생한다고 한다. 그래서 SpringConfig는 제외하고 AOP를 처리하도록 변경해줘야 한다.
@Around("execution(* hello.hellospringdemo..*(..)) && !target(hello.hellospringdemo.SpringConfig)")
다른 분들이 이미 많은 글을 남겨주셔서 빠르게 해결할 수 있었다.
스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 김영한님 강의 내용 참고