AOP
- AOP가 필요한 상황
- AOP 적용
package hello.hellospring.service;
@Transactional
public class MemberService {
/**
* 회원가입
*/
public Long join(Member member) {
long start = System.currentTimeMillis();
try {
validateDuplicateMember(member); //중복 회원 검증
memberRepository.save(member);
return member.getId();
} finally {
long finish = System.currentTimeMillis();
long timeMs = finish - start;
System.out.println("join " + timeMs + "ms");
}
}
/**
* 전체 회원 조회
*/
public List<Member> findMembers() {
long start = System.currentTimeMillis();
try {
return memberRepository.findAll();
} finally {
long finish = System.currentTimeMillis();
long timeMs = finish - start;
System.out.println("findMembers " + timeMs + "ms");
}
}
}
package hello.hellospring.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component // Bean 등록하는 게 눈에 더 잘 띄어 좋은데 일단 여기선 컴포넌트 스캔으로 함
public class TimeTraceAop {
@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");
}
}
}
AOP 적용 전 의존관계
memberService
가 AOP 타겟이 된 경우, 컨트롤러가 memberService
를 부를 때, 가짜 memberService
를 부름 -> 그리고 joinPoint.proceed()
를 만났을 때 실제 memberService
가 호출이 된다.AOP 적용 전 전체 그림
@Autowired // 회원 컨트롤러에 의존관계 추가
public MemberController(MemberService memberService) {
this.memberService = memberService;
System.out.println("memberService = " + memberService.getClass());
}