반응형
AOP가 필요한 상황
모든 메소드의 호출 시간을 측정하고 싶을 때
핵심관심사항: 서비스 로직
공통관심사항: 각 서비스 로직 메소드가 얼마나 걸리는지 구한다.
직접 구하는 방법
public Long join(Member member) {
// 메소드 수행시간을 구한다는 과정에서의 코드
long start = System.currentTimeMillis();
try {
// 중복회원 검증
validateDuplicateMember(member);
memberRepository.save(member);
return member.getId();
} finally {
long finish = System.currentTimeMillis();
long times = finish - start;
System.out.println("join = " + times + "ms");
}
}
문제점
- 회원가입, 회원 조회에 시간을 측정하는 기능은 핵심 관심 사항이 아니다.
- 시간을 측정하는 로직은 공통 관심 사항이다.
- 시간을 측정하는 로직과 핵심 비즈니스의 로직이 섞여서 유지보수가 어렵다.
- 시간을 측정하는 로직을 별도의 공통 로직으로 만들기 매우 어렵다.
- 시간을 측정하는 로직을 변경할 때 모든 로직을 찾아가면서 변경해야 한다.
AOP는 공통관심사항과 핵심관심사항을 분리하는 것이다. (관점지향 프로그래밍)
원하는 곳에 공통 관심 사항을 적용 시키는 방법 이다.
AOP 패키지를 생성
@Aspect 어노테이션을 상단에 입력하여 해당 클래스가 AOP인것을 명시해 준다.
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: 해당 클래스를 빈등록 하는 간단한 방법 -> 서비스 패키지의 SpringConfig에 작성하여도 된다.
//@Component
public class TimeTraceAop {
// 해당 AOP을 어느 부분에 적용할지 선택 -> 여기서는 hello.hellospring 모든 메소드
// 보통 패키지 레밸로 적용하고 원할 경우 검색해서 사용법을 검색해서 사용
// @Around("execution(* hello.hellospring.service..*(..))")
// @Around("execution(* hello.hellospring..*(..))")
// SpringConfig를 통해서 빈 등록을 할 경우 순환참조문제가 발생하여 아래와 같이 AOP대상에서 SpringConfig를 제외시켜준다.
// @Around("execution(* hello.hellospring..*(..)) && !target(hello.hellospring.service.SpringConfig)")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
// 현재 진행중인 메서드를 확인
System.out.println("START: " + joinPoint.toString());
try {
// 다음 메서드로 진행
Object result = joinPoint.proceed();
return result;
} finally {
long finish = System.currentTimeMillis();
long timeMs = finish - start;
System.out.println("END: " + joinPoint.toString() + " " + timeMs + "ms");
}
}
}
joinPoint.proceed(): 프록시 메서드에서 진짜메서드로 진행하도록 하는 명령어
joinPoint.toString(): 진행하는 메서드가 무엇인지 확인하는 명령어
@Around 어노테이션을 이용하여 AOP의 범위를 지정할 수 있다.
SpringConfig클래스를 이용하여 빈 등록을 할 경우 순환참조 에러를 피하기 위해서 SpringConfig 클래스는 범위에서 제외 시켜준다.
SpringConfig클래스에서 빈 등록
// AOP 빈 등록
// 아래 TimeTraceAop을 생성하는 코드도 AOP의 대상으로 지정되기 때문에 @Around어노테이션에서 SpringConfig클래스를 범위에서 제외 시켜줘야 한다.
@Bean
public TimeTraceAop timeTraceAop() {
return new TimeTraceAop();
}
AOP를 적용하면 해당 범위를 입력하면 프록시(해당 가짜 스프링 빈을 만들고) 기술을 이용해서 먼저 거친다음에 진짜 클래스가 동작한다.
MemberController 클래스에서 확인 가능
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
// AOP 프록시 클래스 생성 확인
// memberService: class hello.hellospring.service.MemberService$$EnhancerBySpringCGLIB$$c70ac3a1
System.out.println("memberService: " + memberService.getClass());
}
실행하여 콘솔 확인
반응형
'코드로 배우는 스프링 부트 - 인프런' 카테고리의 다른 글
스프링 데이터 JPA (0) | 2022.08.23 |
---|---|
JPA (0) | 2022.08.22 |
스프링 JDBC Template (0) | 2022.08.19 |
스프링 통합 테스트 (0) | 2022.08.18 |
순수 JDBC (0) | 2022.08.17 |