-
@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