AOP는 관점 지향 프로그래밍으로, 어플리케이션의 핵심 비즈니스 로직과 공통 관심사(cross-cutting concerns)를 분리하여 모듈화하는 프로그래밍 패러다임입니다.
@Pointcut("execution(* com.example.service.*.*(..))")프록시 기반 AOP 구현
메서드 조인포인트만 지원
API 사용 시간 측정 AOP
@Slf4j(topic = "UseTimeAop")
@Aspect
@Component
@RequiredArgsConstructor
public class UseTimeAop {
private final ApiUseTimeRepository apiUseTimeRepository;
// ...
}
@Aspect: 이 클래스가 AOP 클래스임을 명시@Component: 스프링 빈으로 등록@Slf4j: Lombok의 로깅 기능 사용@RequiredArgsConstructor: 필수 필드에 대한 생성자 자동 생성@Pointcut("execution(* com.sparta.myselectshop.controller.ProductController.*(..))")
private void product() {}
@Pointcut("execution(* com.sparta.myselectshop.controller.FolderController.*(..))")
private void folder() {}
@Pointcut("execution(* com.sparta.myselectshop.naver.controller.NaverApiController.*(..))")
private void naver() {}
execution(* package.class.*(..)) 표현식 분석:*: 모든 반환 타입패키지.클래스: 대상 클래스 경로*: 모든 메서드(..): 모든 파라미터@Around("product() || folder() || naver()")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
// ...
}
@Around: 메서드 실행 전후를 모두 제어하는 어드바이스|| 연산자로 결합ProceedingJoinPoint: 원본 메서드 실행을 제어할 수 있는 객체long startTime = System.currentTimeMillis();
try {
Object output = joinPoint.proceed();
return output;
} finally {
long endTime = System.currentTimeMillis();
long runTime = endTime - startTime;
// ...
}
System.currentTimeMillis()로 시작/종료 시간 측정joinPoint.proceed()로 원본 메서드 실행finally 블록에서 실행 시간 계산Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.getPrincipal().getClass() == UserDetailsImpl.class) {
UserDetailsImpl userDetails = (UserDetailsImpl) auth.getPrincipal();
User loginUser = userDetails.getUser();
// ...
}
ApiUseTime apiUseTime = apiUseTimeRepository.findByUser(loginUser).orElse(null);
if (apiUseTime == null) {
apiUseTime = new ApiUseTime(loginUser, runTime);
} else {
apiUseTime.addUseTime(runTime);
}
apiUseTimeRepository.save(apiUseTime);
관심사 분리
재사용성
유지보수성