https://josteady.tistory.com/746
이전에 공부하면서 작성한 포스팅에 앞서, 현재 프로젝트에 적용함에 있어 다시한번 정리하고자 한다.
비슷한 내용이지만, 어노테이션을 직접 만들어본 경험이 없어 AOP 를 적용시키면서 같이 학습하는 좋은 경험이 되었다.
AOP 는 공통 처리 기능(부가 기능) 을 추출해서 프로그램의 여러 곳에서 호출해 사용할 수 있도록 해준다.
내가 만들 AOP의 기능은 단순한 메서드 실행 시간 측정이다.
AOP의 적용 지점은 메서드 , 클래스 ,패키지 등 여러 방식으로 지정이 가능하지만, 나는 내가 원하는 메서드에만 적용하길 원하기 때문에 메서드에 적용시키는 방식을 선택했다.
이유는 조회 같은 대량의 데이터를 불러올 때 측정하고 개선이 필요한지 확인할 수 있지 않을까 라는 생각이 들었기 때문이다.
먼저 gradle 에 의존성을 추가해준다.
// aop 설정
implementation 'org.springframework.boot:spring-boot-starter-aop'
TimerAop 이라는 인터페이스를 만들어준다.
/**
* 특정 메서드에 적용할 수 있는 AOP 메서드 생성
* 용도 : 메서드 실행시간 측정
*/
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface TimerAop {
}
AOP 클래스를 작성한다.
- @PointCut 은 Advice 를 삽입할 수 있는 위치를 의미한다. ( Advice : 부가기능 구현 )
포인트컷의 종류로는 @before , @After , @Around 등 메서드가 수행되는 시점에서 어느 때에 AOP 기능을 구현할 건지 선택할 수 있는데, 실행시간 전, 후로 공유해야 하기 때문에 @Around를 사용한다.
Spring 프레임워크 에서 제공해주는 StopWatch 를 사용하며,
getTotalTimeMillies() 메서드를 사용하면 stopWatch.start(); stopWatch.stop(); 사이에 수행된 메서드의 시간을 측정해준다.
JoinPoint 에서 제공해주는 메서드인 getSignature() 를 사용하면 클라이언트가 호출한 메서드의 시그니처 정보가 저장된 객체를 리턴해주며, getMethod().getName() 을 통해 메서드 이름을 추출할 수 있다.
@Slf4j
@Aspect
@Component
public class ExecutionTimer {
// 조인포인트를 어노테이션으로 설정
@Pointcut("@annotation(com.project.shop.global.common.TimerAop)")
private void timer(){
};
@Around("timer()")
public void ExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
joinPoint.proceed(); // 조인포인트의 메서드 실행
stopWatch.stop();
long totalTimeMillis = stopWatch.getTotalTimeMillis();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String methodName = signature.getMethod().getName();
log.info("실행 메서드: {}, 실행시간 = {}ms", methodName, totalTimeMillis);
}
}
적용하고싶은 메서드에 @TimerAop 를 붙여주면 완료된다.
@TimerAop
@Override
@Transactional(readOnly = true)
public List<GoodsResponse> goodsFindAll(Pageable pageable) {
Page<Goods> goods = goodsRepository.findAll(pageable);
List<GoodsResponse> list = new ArrayList<>();
for (Goods good : goods) {
list.add(GoodsResponse.toResponse(good));
}
return list;
}
참고
'Spring > Spring-detail' 카테고리의 다른 글
spring boot docker mysql 기본설정 (0) | 2023.01.09 |
---|---|
spring 스케줄러(Scheduler) 적용하기 (0) | 2023.01.04 |
Mockito BDDMockito 의 차이점 (1) | 2022.11.04 |
단위테스트(Unit Test) 를 작성하는 이유 (0) | 2022.11.04 |
PSA(Portable Service Abstraction) 이란? (0) | 2022.10.28 |
댓글