AOP
⏲️ when?
- 모든 method의 호출 시간을 측정하고 싶을 때
- 공통 관심 사항(cross-cutting conceern) vs 핵심 관심 사항(core concern)
- 회원 가입 시간, 회원 조회 시간을 측정하고 싶다면
📜 example
- 만약에 사장님이 와서 모든 method의 시간을 알아와라 라고 한다. 그럼 1000개 method를 사용한다면 1000개을 일일이 try catch문으로 잡아서 method명은 00ms 라고 1000번 해야하는데 AOP를 사용한다면 뚝딱이다.
⚖️ 그래서 AOP가 뭔데?
- AOP : Aspect Oriented Programming (관점 지향 프로그래밍)
- 위에서 언급했듯 공통 관심사항과 핵심 관심사항을 나눈다.
- 요렇게 시간측정 로직에 원하는 것을 한 곳에 모으고 적용하는 것이다.
✏️ 작성해보자
@Aspect
public class TimeTraceAop {
@Around("execution(* com.fuckintelli.sibal..*(..))")
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");
}
}
}
- aop package를 한개 만들고 그 안에 timetraceapp class 파일을 만들었다.
@Aspect
: POJO를 인식시키기위해 @Controller라고 적었던 것 처럼 이것도 @Aspect라고 적어주어야 한다.
@Around
: 요 안에 패키지이름, 밑에있는 클래스 명, 파라미터 타입 등등 해서 원하는 조건을 넣을 수 있다. 위 코드처럼 넣으면 모든 패키지에 적용하겠다는 뜻이다.
- 결과 => 이처럼 각 메서드 별로 시간을 체크할 수 있어서 어디서 병목이 되는지도 확인할 수 있다.
- 참고로
execution(* com.fuckintelli.sibal..*(..))
여기서 2번째 ^
는 클래스 이름이 들어가고 (..)
에는 파라미터 값이 들어가는데 여기서는 클래스 개수가 얼마 안 되니까 모든 클래스를 탐색하도록 하였다.
- 또한
@Component
어노테이션을 추가해도 되지만 Spring config 파일에 따로 작성하여 관리하는 것이 다른 개발자로 하여금 "아~ apo를 사용한 class구나~" 하고 인식을 시켜줄 수 있어서 더 좋다.
이점
- 시간을 측정하는 로직을 별도의 공통 로직으로 만들었다.
- 핵심 관심 사항을 깔끔하게 유지할 수 있다.
- 변경이 필요하면 이 로직만 변경하면 된다.
- 원하는 적용 대상을 선택할 수 있다. ->
@Around
로 보통 package 단위로 많이 한다.
(ex) @Around("execution(* com.fuckintelli.sibal.service..*(..))")
서비스 하위 패키지 전체를 대상함.
🛠️ 구동원리
- 프록시라는 기술로 만들어낸 가짜 memeber Serive를 만들어낸다. 그리고 이 가짜 Spring Bean이 끝나면 joinPoint.proceed()를 타고 그 후 진짜를 호출한다.
그래서 만약 모든 package에 aop를 적용했다면 다음과 같이 구동된다.