노션으로 다시 돌아갔습니다 😅

[AOP] Pointcut

by mignon25

포인트컷(Pointcut)

  • 조인 포인트 중에서 어드바이스가 적용될 위치를 선별하는 기능 (조인 포인트를 결정)
  • 스프링 AOP 는 프록시 방식을 사용하므로 메서드 실행 지점만 포인트 컷으로 선별 가능

 

포인트컷 표현식(AspectJ pointcut expression)

  • AspectJ가 제공하는 포인트컷 표현식
  • Pointcut Designator : 포인트컷 지시자
// {} 안에 구성들이 바뀌는 부분
@{어드바이스}("{포인트컷지시자}{parameter}")

// 예시 : hello.hellospring 패키지의 하위에 모두 적용
@Around("execution(* hello.hellospring..*(..))")

 

포인트컷 지시자 (Pointcut Designator, PCD)

종류 설명
execution 메서드 실행 조인트 포인트를 매칭
스프링 AOP에서 가장 많이 사용하며, 기능도 복잡하다.
within 특정 타입 내의 조인 포인트 매칭
args 인자가 주어진 타입의 인스턴스인 조인 포인트
this 스프링 빈 객체(스프링 AOP 프록시)를 대상으로 하는 조인 포인트
target Target 객체(스프링 AOP 프록시가 가리키는 실제 대상)를 대상으로 하는 조인 포인트
@target 실행 객체의 클래스에 주어진 타입의 애너테이션이 있는 조인 포인트
@within 주어진 애너테이션이 있는 타입 내 조인 포인트
@annotation 메서드가 주어진 애너테이션을 가지고 있는 조인 포인트를 매칭
@args 전달된 실제 인수의 런타임 타입이 주어진 타입의 애너테이션을 갖는 조인 포인트
bean 스프링 전용 포인트컷 지시자. 빈의 이름으로 포인트컷을 지정한다.

 

execution 

  • 파라미터 값 표현형태가 특정 형식을 갖추고 있다. 
    => 해당 조건에 만족하는 메서드에서만 AOP 실

// {} : 안의 값이 변경되는 부분
// ? : 보통 생략해서 사용
@{kind-of-Advice}("excution({modifiers-pattern}? {return-type-pattern} {declaring-type-pattern}? {method-name-pattern}({param-pattern}) {throws-pattern}?)")

// 예시
@Around("execution(public * start.aop.controller..*(..))")
  • modifiers-pattern : 접근 제어자 지정 (public, private, *)
  • return-type-pattern : 리턴 타입 지정 (void, String, *)
  • declaring-type-pattern : (패키지 위치 필요)
    • start.aop.controller.* : controller 패키지의 모든 클래스에 적용
    • start.aop.controller.. : controller 패키지 및 하위 패키지의 모든 클래스에 적용
  • method-name-pattern : 메서드 이름 지정
    • addFolders : addFolders() 메서드에만 지정
    • add* : add 로 시작하는 모든 메서드에 적용
  • param-pattern : 특정 파라미터 지정
    • ({특정 클래스 주소}) : 그 클래스/인터페이스가 파라미터인 메서드에 적용
    • () : 인수 없음
    • (*) : 인수 1개 (타입 상관없음)
    • (..) : 인수, 타입 상관없음

 

포인트컷 표현식 사용 예제 

@Pointcut(
          "execution("    // PCD execution 지정
        + "[접근제한자 패턴] "  // public
        + "리턴타입 패턴"       // long
        + "[패키지명, 클래스 경로 패턴]"          // com.moong.ahea.UserService
        + "메소드명 패턴(파라미터 타입 패턴|..)"  // .findUserId(String)
        + "[throws 예외 타입 패턴]"             // throws RuntimeException
        +")"   
          )

// 모든 패키지에 포함된 클래스 중에, 클래스 이름이 Service로 끝나는 클래스
@Pointcut("execution( * *..*Service.findUserId(..) )")

// 최소한의 필수 규칙들 → 리턴타입 메소드명(파라미터)
@Pointcut("execution( * findUserId(..) )")

// find로 시작하는 메소드
@Pointcut("execution( * find*(..) )")
  • 모든 공개 메서드 실행
    • execution(public * *(..))
  • 메서드 이름이 set 으로 시작하는 모든 메서드 실행
    • execution(* set*(..))
  • service 패키지에 정의된 메서드 실행
    • execution(* com.xyz.service.*.*(..))
  • 서비스 패키지 또는 하위 패키지의 모든 메서드 실행
    • execution(* com.xyz.service..*.*(..))
  • 서비스 패키지의 UserServiceImpl 클래스를 직접 지정, 해당 클래스의 모든 메서드 선택
    • execution(* com.xyz.service.UserServiceImpl.*(..))
  • 클래스 이름이 ServiceImpl로 끝나는 클래스의 모든 메서드 선택
    • execution(* *..*ServiceImpl.*(..))
  • hello 라는 이름을 가진 메서드 선정, 모든 파라미터 종류 허용
    • execution(* hello(..))
  • 패키지에 상관없이 Target 이라는 모든 클래스에 적용
    • execution(* *..Target.*(..))
  • 서비스 패키지 내의 모든 조인 포인트(only Spring AOP)
    • within(com.xyz.service.*)
  • 서비스 패키지 또는 하위 패키지 내의 모든 조인 포인트(only Spring AOP)
    • within(com.xyz.service..*)
  • AccountService 프록시가 인터페이스를 구현하는 모든 조인 포인트(only Spring AOP)
    • this(com.xyz.service.AccountService)
  • AccountService 대상 객체가 인터페이스를 구현하는 모든 조인 포인트 (only Spring AOP)
    • target(com.xyz.service.AccountService)
  • 단일 매개변수를 사용하고 런타임에 전달된 인수가 Serializable과 타입이 같은 모든 조인 포인트 (only Spring AOP)
    • args(java.io.Serializable)
  • 대상 객체에 @Transactional 애너테이션이 있는 모든 조인 포인트 (only Spring AOP)
    • @target(org.springframework.transaction.annotation.Transactional)
  • 실행 메서드에 @Transactional 애너테이션이 있는 조인 포인트(only Spring AOP)
    • @annotation(org.springframework.transaction.annotation.Transactional)
  • 단일 매개 변수를 사용하고 전달된 인수의 런타임 유형이 @Classified 애너테이션을 갖는 조인 포인트 (only Spring AOP)
    • @args(com.xyz.security.Classified)
  • tradeService 라는 이름을 가진 스프링 빈의 모든 조인 포인트 (only Spring AOP)
    • bean(tradeService)
  • 와일드 표현식 *Service 라는 이름을 가진 스프링 빈의 모든 조인 포인트
    • bean(*Service)

 

 

포인트컷 표현식 결합

  • && , ||
  • 포인트컷 표현식은 위의 3가지 연산자를 사용하여, PCD를 조합하여 사용할 수 있다.
  • 조합할 때는, 포인트컷이 적용된 대상의 이름 사용
@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {} // (1)

@Pointcut("within(com.xyz.myapp.trading..*)")
private void inTrading() {} // (2)

@Pointcut("anyPublicOperation() && inTrading()")
private void tradingOperation() {} // (3)

1. 접근 제한자 패턴이 public 인 모든 메서드에 적용

2. com.xyz.myapp.trading 패키지 및 하위 패키지의 모든 클래스의 모든 메서드에 적용

3. 1,2를 모두 만족시키는 모든 메서드에 적용

 

 

 

References

https://gmoon92.github.io/spring/aop/2019/05/06/pointcut.html

'Spring' 카테고리의 다른 글

[AOP] Advice  (0) 2023.04.12
[AOP] JoinPoint  (0) 2023.04.12
조회한 빈이 모두 필요할 때 - List, Map 사용  (0) 2023.04.12
@Autowired 사용할 때 빈 이름 중복 매칭 문제 - @Qualifier, @Primary  (0) 2023.04.11
AOP의 용어  (0) 2023.04.11

블로그의 정보

Mignon'S Dev Log

mignon25

활동하기