1. AOP가 필요한 상황
🌱 모든 메소드의 호출 시간을 측정하고 싶다면?
- 메소드 시작과 끝에 메소드 호출시간 코드 집어넣기 (시간 측정 로직을 모든 메소드에 다 집어넣기)
public Long join(Member member)
{
long start = System.currentTimeMillis();
try
{
//핵심 비지니스 로직
}
finally
{
long finish = System.currentTimeMillis(); long timeMs = finish - start;
System.out.println("join " + timeMs + "ms");
}
}
- try - finally 구문 사용
- try 내부 : 핵심 비지니스 로직
- finally : 시간 측정 로직 (핵심 비지니스 로직이 끝날때 시간을 찍어야함, finally는 항상 들어오니까)
- 모든 메소드에 해당 로직 추가하기
🌱 문제점
- 시간을 측정하는 기능(finally 내부)은 핵심 로직이 아님
- 시간을 측정하는 로직은 공통 기능==공통 관심사항임
- 시간을 측정하는 로직과 핵심 비즈니스 로직이 섞여있어서 유지 보수가 어렵다.
- 시간을 측정하는 로직을 뽑아내서 별도의 공통 로직으로 만들기 매우 어렵다. (메소드로 뽑아내기 어려움)
- +) 특히 시작부분, 끝 부분에 로직이 들어가있기 때문에..!!
- 시간을 측정하는 로직을 변경할 때 모든 로직을 찾아가면서 변경해야한다. ex) 시간측정 단위를 변경하고 싶을 때 +) 특히 시작부분, 끝 부분에 로직이 들어가있기 때문에..!!
2. AOP 적용
🌱 AOP란?
- Aspect Oriented Programming
- 공통 관심사항과 핵심 관심 사항을 분리하는 것
- 시간 측정 로직을 한군데 모으고 내가 원하는 곳에 공통 관심 사항 적용함
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;
@Component
@Aspect
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라고 하나 만들고 그 안에 TimeTraceAop 클래스를 만듦
- @Component 사용 대신 스프링빈에 직접 등록해주는게 좋음
- @Aspect => AOP로 적용하기 위해 적어줘야함
- @Around 활용해서 ⇒ 공통관심사항을 어디에다 적용할건지 타겟팅해줌
- 시간을 측정해서 ⇒ 어디서 병목현상(트래픽 밀림)이 있는지 찾을 수 있음
🌱 해결
- 핵심 관심사항과 공통 관심사항을 분리했음
- 시간을 측정하는 로직을 별도의 공통로직으로 만들었음
- 핵심 관심 사항을 깔끔하게 유지할 수 있다.
- 변경이 필요하면 이 로직만 변경하면 됨
- 원하는 적용대상을 선택할 수 있음 (@Around)
🌱 AOP 적용 전 의존 관계
- 컨트롤러에서 서비스 호출할 때 그냥 호출
- Controller가 Service에 의존하고 있음 => Controller에서 메소드 호출 -> Service 메소드 호출
🌱 AOP 적용 후
- 가짜 멤버 서비스를 만들어냄 == 프록시라고 함
- 스프링 컨테이너 동작 : 컨테이너에 스프링 빈 등록할 때 가짜 스프링빈을 앞에 세워둠
- 가짜 스프링빈이 끝나면 그때 진짜 memberService 호출
- helloController가 호출하는 건 진짜 멤버 서비스가 아니라 가짜 멤버 서비스
- 이때 사용되는 기술 프록시 기술 ⇒ 스프링 핵심 강의때 ..
+) 프록시 확인해보기
- 멤버 컨트롤러에서 멤버 서비스가 인젝션될 때 => memberService.getClass() 찍어보기
- 멤버 서비스를 가지고 복제를 해서 코드를 조작하는 기술 (== 프록시)
'3-2기 스터디 > Spring 입문' 카테고리의 다른 글
[6주차] 스프링 핵심 원리 이해1 - 예제 만들기 (0) | 2022.05.20 |
---|---|
[5주차] 객체 지향 설계와 스프링 (0) | 2022.05.11 |
[3주차] 스프링 DB 접근 기술 (0) | 2022.05.04 |
[2주차] 회원 관리 예제, 스프링 빈과 의존관계 (0) | 2022.05.04 |
[1주차] 프로젝트 환경 설정, 스프링 웹 개발 기초 (0) | 2022.04.06 |
댓글