스프링 AOP 적용

앞서 간단하게 프록시 패턴을 통해 적용했던 AOP를 스프링 AOP로 변경해보자.

package me.cjkim.demoSpring51;

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 PerfAspect {

    @Around("execution(* me.cjkim..*.EventService.*(..))") //me.cjkim 패키지 하위 모든 클래스 중 EventService 클래스의 모든 메소드에 적용
    public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{
        long begin = System.currentTimeMillis();
        Object retVal = pjp.proceed();
        System.out.println(System.currentTimeMillis() - begin);
        return retVal;
    }
}

@Aspect를 통해 해당 클래스는 Aspect라고 명시해주었다. logPerf메소드는 advice를 맡고 있으며, 횡단 관심사로 어떤 일을 진행할지를 정의하였다. @Around어놑이션을 통해 포인트 컷의 실행 전 후에 적용된다는 것을 알 수 있으며, 어노테이션의 매개변수로 포인트 컷을 지정, 즉 조인 포인트를 정의하였다. 만일 특정 메소드는 적용하고 싶지 않다면, 어노테이션을 이용해서 제외시킬 수 있다.

package me.cjkim.demoSpring51;

import java.lang.annotation.*;

@Documented // JavaDoc이 어노테이션의 존재를 표기하도록 지정
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD) // 메소드만 타켓으로 지정한다는 것을 명시
public @interface PerfLogging {
}

PerfLogging이라는 어노테이션을 만들었다. 여기서 주의해야 할 점은 RetentionPolicy 값은 클래스 이상으로 지정해야 한다는 점이다(기본 값은 클래스이다).
RetentionPolicy는 어노테이션 정보를 언제까지 유지할 것인지에 대한 정보이다. 클래스까지 정의하면 클래스 파일까지 유지하겠다는 의미이며, 컴파일 후에도 어노테이션 정보가 남아 있다. 그런데 만일 Source로 변경하게되면, 컴파일 하고나면 어노테이션 정보가 사라진다. 또 런타임까지는 유지할 필요는 없기에 클래스로 지정해두자.

그리고 어드바이스를 지정하고 싶은 메소드에만 어노테이션을 추가한 뒤, aspect의 @Around 어노테이션의 설정 값을 아래와 같이 변경하자.

package me.cjkim.demoSpring51;

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 PerfAspect {

    @Around("@annotation(PerfLogging)")
    public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{
        long begin = System.currentTimeMillis();
        Object retVal = pjp.proceed();
        System.out.println(System.currentTimeMillis() - begin);
        return retVal;
    }
}

위와 같이 설정한 후 실행하면 내가 어노테이션을 지정한 메소드에만 해당 기능이 적용되는 것을 볼 수 있다.

포인트 컷 정의

  • @PointCut(표현식)
  • 주요 표현식
    • execution
    • @annotation
    • bean
  • 포인트컷 조합 : &&,   , ! 등 연산자등을 이용하여 여러 포인트컷 지정 가능

어드바이스 정의

  • @Before : 실행 직전
  • @AfterReturning : 성공적으로 실행 후
  • @AfterThrowing : 예외 발생 후
  • @Around : 실행 전 후

참고 자료

  1. 스프링 프레임워크 핵심 기술

oksusutea's blog

꾸준히 기록하려고 만든 블로그