AOP - 적용(어드바이스 추가)

박찬우·2024년 2월 16일

스프링

목록 보기
62/88

에스팩트

@Slf4j
@Aspect
public class AspectV3 {

    @Pointcut("execution(* hello.aop.order ..*(..))")
    private void allOrder(){} // 포인트컷 시그니처

    @Pointcut("execution(* *..*Service.*(..))")
    private void allService(){} // 포인트컷 시그니처

    @Around("allOrder()")
    public Object doLog(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("[log] {}", joinPoint.getSignature());
        return joinPoint.proceed();
    }

    @Around("allOrder() && allService()")
    public Object doTransaction(ProceedingJoinPoint joinPoint) throws Throwable
    {
        try {
            log.info("[트랜잭션 시작] {}", joinPoint.getSignature());
            Object result = joinPoint.proceed();
            log.info("[트랜잭션 커밋] {}", joinPoint.getSignature());
            return result;
        } catch (Exception e) {
            log.info("[트랜잭션 롤백] {}", joinPoint.getSignature());
            throw e;
        } finally {
            log.info("[리소스 릴리즈] {}", joinPoint.getSignature());
        }
    }
}
  • allOrder() 포인트컷은 hello.aop.order 패키지와 하위 패키지를 대상으로 한다.
  • allService() 포인트컷은 타입 이름 패턴이 *Service 를 대상으로 하는데 쉽게 이야기해서 XxxService 처럼 Service 로 끝나는 것을 대상으로 한다. *Servi* 과 같은 패턴도 가능하다.
  • 여기서 타입 이름 패턴이라고 한 이유는 클래스, 인터페이스에 모두 적용되기 때문이다.
  • @Around("allOrder() && allService()")
    • 포인트컷은 이렇게 조합할 수 있다. && (AND), || (OR), ! (NOT) 3가지 조합이 가능하다.
    • hello.aop.order 패키지와 하위 패키지 이면서 타입 이름 패턴이 *Service 인 것을 대상으로 한다.
    • 결과적으로 doTransaction() 어드바이스는 OrderService 에만 적용된다.
    • doLog() 어드바이스는 OrderService , OrderRepository 에 모두 적용된다.
  • 포인트컷이 적용된 AOP 결과는 다음과 같다.
    • orderService : doLog() , doTransaction() 어드바이스 적용
    • orderRepository : doLog() 어드바이스 적용

TEST

@Slf4j
@SpringBootTest
@Import(AspectV3.class)
public class AopTest {
    @Autowired
    OrderService orderService;
    @Autowired
    OrderRepository orderRepository;

    @Test
    void aopInfo() {
        log.info("isAopProxy, orderService={}",
                AopUtils.isAopProxy(orderService));
        log.info("isAopProxy, orderRepository={}",
                AopUtils.isAopProxy(orderRepository));
    }

    @Test
    void success() {
        orderService.orderItem("itemA");
    }

    @Test
    void exception() {
        assertThatThrownBy(() -> orderService.orderItem("ex"))
                .isInstanceOf(IllegalStateException.class);
    }
}

결과

profile
진짜 개발자가 되어보자

0개의 댓글