1. AOP가 필요한 상황
- 모든 메소드의 호출시간을 측정하고 싶음(회원가입 시간, 회원조회 시간 측정 원함)
- 공통 관심 사항(AOP) vs 핵심 관심 사항
public class MemberService {
public Long join(Member member) {
long start = System.currentTimeMillis();
try {
validateDuplicateMember(member);
memberRepository.save(member);
return member.getId();
} finally {
long finish = System.currentTimeMillis();
long timeMs = finish - start;
System.out.println("join " + timeMs + "ms");
}
}
}
- 모든 메서드에 try ~ finally를 붙여야함
- 하지만, 이는 핵심 관심사항이 아니기에 핵심 비즈니스 로직과 섞여 유지보수도 어려움
2. AOP를 이용하면?
[ 코드 ]
package hello.hellospring.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
public class TimeTraceAop {
@Around("execution(* hello.hellospring..*(..))")
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");
}
}
}
@Component
하면 등록되지만, SpringConfig에서 @Bean으로 등록하면 한눈에 볼 수 있음
- 핵심 로직을 유지하면서, 시간 재는 로직을 추가할 수 있음
- 변경이 필요하면 이 로직만 변경하면 됨
[ AOP 적용 후 전체 그림 ]
- 프록시에 먼저 접근해 시간을 측정하면서 실제 로직을 들어간다.