ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • @Pointcut - 포인트컷 분리
    스프링/스프링 AOP 2023. 9. 22. 14:36

    AOP 동작을 위한 service, repository 코드

     

    OrderRepository.class

    @Slf4j
    @Repository
    public class OrderRepository {
        public String save(String itemId) {
            log.info("[orderRepository] 실행");
            //저장 로직
            if (itemId.equals("ex")) {
                throw new IllegalStateException("예외 발생!");
            }
            return "ok";
        }
    }

     

     

    OrderService.class

    @Slf4j
    @Service
    public class OrderService {
        private final OrderRepository orderRepository;
    
        public OrderService(OrderRepository orderRepository) {
            this.orderRepository = orderRepository;
        }
    
        public void orderItem(String itemId) {
            log.info("[orderService] 실행");
            orderRepository.save(itemId);
        }
    }

     

    AOP가 적용되는지 확인을 위한 Service와 Repository 코드이다. 진짜 간단하게 로그를 통해 어떤 것이 실행되는지만 적어놨다.

     

     

    포인트컷 분리 전 - @Around에 경로

    @Slf4j
    @Aspect
    public class AspectV1 {
    
        @Around("execution(* hello.aop.order..*(..))") // 포인트컷
        public Object doLog(ProceedingJoinPoint joinPoint) throws Throwable {
            log.info("[log] {}", joinPoint.getSignature()); // joinPoint 시그니처 (메서드 뭐 호출되었는지)
            return joinPoint.proceed();
        }
    }

    이전에도 포스팅했지만 @Aspect 어노테이션을 활용하면 aop를 쉽게 적용할 수 있다.

     

     

     

    포인트컷 분리 전 - @Poincut 사용

    @Slf4j
    @Aspect
    public class AspectV2 {
        
        // hello.aop.order 패키지와 하위 패키지
        @Pointcut("execution(* hello.aop.order..*(..))") // 포인트컷
        private void allOrder(){}
    
        @Around("allOrder()")
        public Object doLog(ProceedingJoinPoint joinPoint) throws Throwable {
            log.info("[log] {}", joinPoint.getSignature());
            return joinPoint.proceed();
        }
    }

    @Around에 포인트컷의 경로를 넣는 것이 아니라 @Pointcut 어노테이션을 이용해서 거기에 경로를 설정할 수도 있다. @Around 어노테이션에는 allOrder()라는 메서드를 넣어주면 된다.

     

     

    allOrder()의 코드 내용은 비워두고 반환 타입은 무조건 void여야 한다.

     

    이렇게 하면 doLog2() 등 다른 aop가 있을 때 allOrder()를 넣어줘서 같은 포인트 컷을 넣어줄 수 있다.

     

    물론 @Around와 @Poincut 어디에 경로를 넣든 결과는 똑같다.

     

    하나의 포인트컷 표현식으로 여러 어드바이스에서 함께 사용할 수도 있으며 public으로 선언하면 다른 클래스에 있는 외부 어드바이스에서도 포인트컷을 함께 사용할 수도 있다.

     

     

     

    Pointcut.class

    package hello.aop.order.aop;
    
    import org.aspectj.lang.annotation.Pointcut;
    
    public class Pointcuts {
        @Pointcut("execution(* hello.aop.order..*(..))")
        public void allOrder(){}
    
        @Pointcut("execution(* *..*Service.*(..))")
        public void allService(){}
    
        // 위 2개의 동시 조건 포인트컷
        @Pointcut("allOrder() && allService()")
        public void orderAndService(){}
    }

    포인트컷 클래스를 만들고 그 클래스의 경로를 입력하면 포인트컷을 외부에서 사용할 수 있다.

    @Pointcut("hello.aop.order.aop.Pointcuts.allOrder()")
    private void allOrder(){}

    포인트컷의 경로.클래스이름.메서드 이름을 통해 포인트컷의 경로를 넣어줬다.

    '스프링 > 스프링 AOP' 카테고리의 다른 글

    어드바이스 종류  (0) 2023.09.22
    어드바이스 순서  (0) 2023.09.22
    @Aspect 프록시  (0) 2023.09.20
    빈 후처리기  (0) 2023.09.17
    어드바이저의 실제 적용  (0) 2023.09.17
Designed by Tistory.