📍회원 가입 시간을 측정해보기 위한 MemberService
@Transactional
public class MemberService {
...
// 회원가입
public Long join(Member member) {
// 시작할 때 시간 측정
long start = System.currentTimeMillis();
try {
// 이름이 같은 중복 회원 X
validateDuplicateMember(member);
// member를 저장소에 저장
memberRepository.save(member);
return member.getId();
} finally { // try가 끝날 때 실행하는 동작
// 끝날 때 시간 측정
long finish = System.currentTimeMillis();
long timeMs = finish - start;
System.out.println("timeMS : "+ timeMs + "ms");
}
}
...
}
AOP
- Aspect Oriented Programming
- 공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern) 분리
- 원하는 곳에 공통 관심 사항 적용
📍시간 측정 AOP TimeTraceAop 생성
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class TimeTraceAop {
// AOP를 사용할 위치(hello.hellospring 하위 모든 메서드)
@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");
}
}
}
📍SpringConfig 등록
@Configuration
public class SpringConfig {
...
// Spring bean에 TimeTraceAop 등록
@Bean
public TimeTraceAop timeTraceAop() {
return new TimeTraceAop();
}
}
💡 AOP를 사용한다면 ?
- 회원가입, 회원 조회등 핵심 관심사항과 시간을 측정하는 공통 관심 사항을 분리하게 됨
- 시간을 측정하는 로직을 별도의 공통 로직으로 만듦
- 핵심 관심 사항을 깔끔하게 유지
- 변경이 필요하면 이 로직만 변경
- 원하는 적용 대상을 선택 가능
AOP를 적용하면,
1. memberService라는 프록시를 만들고 진짜 memberService 앞에 가짜 memberService를 spring bean으로 등록
2. 가짜 memberService가 종료되면 joinPoint.proceed() 를 통해 실제 memberService를 호출
=> memberController가 호출해주는 건 진짜 memberService가 아니라 가짜 memberService 이다.