AOP가 필요한 상황
- 모든 메소드의 호출 시간을 측정하고 싶을 경우
- 회원 가입 시간, 회원 조회 시간을 측정하고 싶다면?
👉🏻 MemberService 회원 가입, 조회 시간 측정 추가
📁 service/MemberService
@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");
}
}
}
- 회원 가입 시간 측정 결과
- 회원 조회 시간 측정 결과
문제점
- 회원 가입, 회원 조회에 시간을 측정하는 기능은 핵심 관심 사항이 아니다.
- 시간을 측정하는 로직은 공통 관심 사항이다.
- 위와 같이 구성한다면 시간을 측정하는 로직과 핵심 비즈니스 로직이 섞여서 유지보수가 어렵다.
- 시간을 측정하는 로직을 별도의 공통 로직으로 만들기 매우 어렵다.
- 시간을 측정하는 로직을 변경 할 때 모든 로직을 찾아가면서 변경해야 한다.
AOP 적용
- Aspect Oriented Programming (관점 지향 프로그래밍)
- 공통 관심 사항과 핵심 관심 사항을 분리하는 기술이다.
👉🏻 시간 측정 AOP 등록
📁 aop/TimeTraceAop
@Aspect
@Component // Bean에 등록
public class TimeTraceAop {
@Around("execution(* hello.hellospring..*(..))") // 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 적용 대상을 선택할 수 있다.
AOP 동작 방식
💡 AOP 적용 전 의존 관계
💡 AOP 적용 후 의존 관계
- 스프링 컨테이너는 memberService에 AOP가 적용되면 가짜 프록시를 만들어 내서
이 프록시를 통해 AOP가 모두 실행되고, joinPoint.proceed()하면 실제 memberService가 호출이 된다.
💡 AOP 적용 전 전체 그림
💡 AOP 적용 후 전체 그림
'🌱 Spring > Core' 카테고리의 다른 글
[기본] #4 스프링 컨테이너, 스프링 빈 (0) | 2022.02.23 |
---|---|
[기본] #3 객체 지향 원리 적용 (0) | 2022.02.22 |
[기본] #2 회원, 주문, 할인 도메인 개발 및 테스트 (0) | 2022.02.21 |
[기본] #1 객체 지향 설계와 스프링 (0) | 2022.02.18 |
[입문] #6 DB 접근기술(JDBC, JdbcTemplate, JPA, SpringJPA) (0) | 2022.02.16 |
[입문] #5 웹 MVC 개발 (0) | 2022.02.15 |
[입문] #4 스프링 빈과 의존관계 (0) | 2022.02.15 |
[입문] #3 회원관리 예제 만들기 (0) | 2022.02.15 |