@Aspect AOP

slee2·2022년 3월 21일
0

적용

스프링 어플리케이션에 프록시를 적용하려면 포인트컷과 어드바이스로 구성되어 있는 어드바이저(Advisor)를 만들어서 스프링 빈으로 등록하면 된다.
그러면 나머지는 자동 프록시 생성기가 알아서 해준다.

스프링은 @Aspect 어노테이션으로 매우 편리하게 포인트컷과 어드바이스로 구성되어 있는 어드바이저 생성 기능을 지원한다.

참고
@Aspect는 관점 지향 프로그래밍(AOP)를 가능하게 하는 AspectJ 프로젝트에서 제공하는 어노테이션이다.

LogTraceAspect

package hello.proxy.config.v6_aop.aspect;

import hello.proxy.trace.TraceStatus;
import hello.proxy.trace.logtrace.LogTrace;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import java.lang.reflect.Method;

@Slf4j
@Aspect
public class LogTraceAspect {

    private final LogTrace logTrace;

    public LogTraceAspect(LogTrace logTrace) {
        this.logTrace = logTrace;
    }

    @Around("execution(* hello.proxy.app..*(..))")
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
        TraceStatus status = null;

//        log.info("target={}", joinPoint.getTarget()); //실제 호출 대상
//        log.info("getArgs={}", joinPoint.getArgs()); //전달인자
//        log.info("getSignature={}", joinPoint.getSignature()); //join point 시그니처
        
        try {
            String message = joinPoint.getSignature().toShortString();
            status = logTrace.begin(message);

            //로직 호출
            Object result = joinPoint.proceed();

            logTrace.end(status);
            return result;
        } catch (Exception e) {
            logTrace.exception(status, e);
            throw e;
        }
    }
}
  • @Aspect: 어노테이션 기반 프록시를 적용할때 필요
  • @Around("execution(* hello.proxy.app..*(..))")
    • @Around의 값에 포인트컷 표현식을 넣는다. 표현식은 AspectJ 표현식을 사용
    • @Around의 메서드는 어드바이스(Advice)
  • ProceedingJoinPoint joinPoint: 어드바이스에서 살펴본 MethodInvocation invocation과 유사한 기능이다.
  • joinPoint.proceed(): 실제 호출 대상(target)을 호출

AopConfig

동작 설명

자동 프록시 생성기(AnnotationAwareAspectJAutoProxyCreator)는 Advisor를 자동으로 찾아와서 필요한 곳에 프록시를 생성하고 적용해준다.
자동 프록시 생성기는 여기에 추가로 @Aspect를 찾아서 Advisor로 만들어준다.

자동 프록시 생성기는 2가지 일을 한다.
1. @Aspect를 보고 어드바이저로 변환해서 저장한다.
2. 어드바이저를 기반으로 프록시를 생성한다.

과정
1. 스프링 어플리케이션 로딩 시점에 자동 프록시 생성기를 호출한다.
2. 모든 @Aspect 빈을 조회한다.
3. @Aspect 어드바이저 빌더를 통해 어드바이저를 생성한다.
4. @Aspect 어드바이저 빌드 내부에 생성한 어드바이저를 저장한다.

@Aspect 어드바이저 빌더
BeanFactoryAspectJAdvisorBuilder 클래스이다.
@Aspect의 정보를 기반으로 포인트컷, 어드바이스, 어드바이저를 생성하고 보관하는 것을 담당한다.
@Aspect의 정보를 기반으로 어드바이저를 만들고, @Aspect 어드바이저 빌더 내부 저장소에 캐시한다.
캐시에 어드바이저가 이미 만들어져 있는 경우 캐시에 저장된 어드바이저 반환.

  1. 스프링 빈 대상이 되는 객체를 생성한다. (@Bean, 컴포넌트 스캔 포함)
  2. 빈 저장소에 등록하기 전에 빈 후처리기에 전달한다.
  3. 스프링 컨테이너에서 Advisor빈을 모두 조회한다.
  4. @Aspect 어드바이저 빌더 내부에 저장된 Advisor를 모두 조회.
  5. 포인트컷을 사용해서 해당 객체가 프록시를 적용할 대상인지 아닌지 판단한다.
  6. 프록시 생성
  7. 빈 등록

정리

실무에서 프록시를 적용할때는 대부분 @Aspect를 이용한다.

지금까지 우리가 진행한 어플리케이션 전반에 로그를 남기는 기능은 특정 기능 하나에 관심이 있는 기능이 아니다.
어플리케이션 여러 기능들 사이에 걸쳐서 들어가는 관심사이다.
이것을 바로 횡단 관심사라고 한다.

이제 이 횡단 관심사를 해결하는 AOP를 배울 예정

0개의 댓글