반응형

# AOP (AOP : Aspect Oriented Programming)

## AOP가 필요한 상황

  • 모든 메서드 호출 시간 측정 / 회원 가입, 회원 조회 시간 등 측정 등.

currentTimeMillis() 를 사용한 방법

/**
* 회원 가입
*/
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);
    }
}
  • currentTimeMillis() 를 적용하여 회원가입 시간 측정 시 아래와 같이 측정되는것을 확인 할 수 있음.

문제점

  • 시간을 측정하는 기능은 핵심 관심 사항이 아님.
  • 시간을 측정하는 기능은 핵심 로직이 아닌, 공통 로직. (공통 관심 사항 - cross-cutting concern)
  • 위와 같이 시간 측정 로직, 핵심 비즈니스 로직이 섞여있는 경우 유지보수가 어렵다.
  • 위와 같이 시작 측정 로직이 있는 경우 변경이 필요하다면, 모든 로직을 찾아서 변경해야 하는 어려움이 존재.

## AOP 적용

  • 공통 관심 사항(cross-cutting concern), 핵심 관심 사항(core concern) 분리.

시간 측정 AOP 등록

  • AOP의 경우 @Aspect 에노테이션 추가 필요.
  • AOP의 경우 아래와 같이 @Component 에노테이션 추가 또는 SpringConfig에 직접 등록하여 사용.
@Aspect
@Component
public class TimeTraceAop {
@Bean
public TimeTraceAop timeTraceAop() {
    return new TimeTraceAop();
}

timeTraceAop

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 적용 후 의존관계

  • memberService 에 AOP가 적용되면 스프링 컨테이너에서 프록시 memberService (가짜 memberService) 를 생성해서 호출, joinPoint.proceed() 가 끝나면 내부적으로 진짜 memberService 호출 해줌.
반응형

+ Recent posts