- @Aspect: AOP 기능을 사용할 것임을 알리기
- Spring 빈(Bean) 클래스에만 적용 가능합니다.
- Spring 빈(Bean) 클래스에만 적용 가능합니다.
- 어드바이스: 기능의 어느 지점에 동작할지 알리기
- @Around: '핵심기능' 수행 전과 후 (@Before + @After)
- @Before: '핵심기능' 호출 전 (ex. Client 의 입력값 Validation 수행)
- @After: '핵심기능' 수행 성공/실패 여부와 상관없이 언제나 동작 (try, catch 의 finally() 처럼 동작)
- @AfterReturning: '핵심기능' 호출 성공 시 (함수의 Return 값 사용 가능)
- @AfterThrowing: '핵심기능' 호출 실패 시. 즉, 예외 (Exception) 가 발생한 경우만 동작 (ex. 예외가 발생했을 때 개발자에게 email 이나 SMS 보냄)
- 포인트컷: 어느 기능에 적용할지 알리기
- 포인트컷 Expression Language
- 포인트컷 Expression Language
형태
execution(modifiers-pattern? return-type-pattern declaring-type-pattern?
method-name-pattern(param-pattern) throws-pattern?)
예시
@Around("execution(public * com.sparta.myselectshop.controller..*(..))")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable { ... }
- ? 는 생략 가능
- modifiers-pattern
: public, private, * - return-type-pattern
: void, String, List<String>, ***** - declaring-type-pattern
- 클래스명 (패키지명 필요)
- com.sparta.myselectshop.controller.* - controller 패키지의 모든 클래스에 적용
- com.sparta.myselectshop.controller.. - controller 패키지 및 하위 패키지의 모든 클래스에 적용
- method-name-pattern(param-pattern)
- 함수명(method-name-pattern)
- addFolders : addFolders() 함수에만 적용
- add* : add 로 시작하는 모든 함수에 적용
- 파라미터 패턴(param-pattern)
- (com.sparta.myselectshop.dto.FolderRequestDto) - FolderRequestDto 인수 (arguments) 만 적용
- () - 인수 없음
- (*) - 인수 1개 (타입 상관없음)
- (..) - 인수 0~N개 (타입 상관없음)
- 함수명(method-name-pattern)
- @Pointcut
- 포인트컷 재사용 가능
- 포인트컷 결합 (combine) 가능
@Aspect
@Component
@RequiredArgsConstructor
public class UseTimeAop {
private final ApiUseTimeRepository apiUseTimeRepository;
@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() {}
@Around("product() || folder() || naver()")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
try {
// 핵심 기능 수행, 여기서는 Controller의 해당 메서드를 수행시킨다.
Object output = joinPoint.proceed();
return output;
} finally {
long endTime = System.currentTimeMillis();
long runTime = endTime - startTime;
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);
}
}
}
}
'Spring > 팀스파르타' 카테고리의 다른 글
51. Spring의 properties 파일을 이용한 에러 메시지 관리 (1) | 2024.12.09 |
---|---|
50. ExceptionHandler, Spring의 Global 예외처리 (1) | 2024.12.06 |
48. OAuth로 카카오 로그인 및 회원 가입 (0) | 2024.12.06 |
47. 소셜 로그인 - OAuth (0) | 2024.12.06 |
44. Mockito (0) | 2024.12.06 |