개발 기록

> [AOP] 3. 포인트컷(PointCut)의 다양한 표현식 본문

Spring

> [AOP] 3. 포인트컷(PointCut)의 다양한 표현식

1z 2022. 10. 27. 10:52

 

 

1. 포인트컷 

advice 가 실행되는 시점을 제어한다.

 

(1) 사용법

1. 포인트컷 표현식은 @Pointcut 어노테이션의 값으로 나타낸다.

@Pointcut("within(@org.springframework.stereotype.Repository *)")
public void repositoryClassMethods() {}Copy

 

2. pointcut signature :  advice 어노테이션이 해당 포인트 컷의 메소드명을 참조한다.

@Around("repositoryClassMethods()")
public Object measureMethodExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
    ...
}Copy

 

(2) 명시자

 
종류  설명
execution Advice를 적용할 메서드를 명시 할 때 사용
within 타입 패턴 내에 속하는 메서드를 JoinPoint로 설정되도록 명시할 때 사용
bean 스프링 빈을 이용하여 JoinPoint를 설정 (스프링 2.5 부터 지원)

 

(3) 리턴타입 지정

// server.spring.aop 패키지에 속해있고, 파라미터가 1개인 모든 메서드
@Pointcut("execution(public Integer server.spring.aop.*.*(*))")

 

표현식  설명
* 모든 리턴타입 허용
void 리턴타입이 void인 메소드 선택
!void 리턴타입이 void가 아닌 메소드 선택

 

(4) 패키지 지정

 

표현식  설명
server.spring.service 정확하게 server.spring.service 패키지만 선택
server.spring.domain.. server.spring.domain  패키지로 시작하는 모든 패키지 선택

 

(5) 클래스 지정

// server.spring 패키지 및 하위 패키지에 속해있고, 이름이 Service르 끝나는 인터페이스의 파라미터가 0개 이상인 모든 메서드
@Pointcut("execution(* server.spring..*Service.*(..))")

 

표현식  설명
User 정확하게 User 클래스만 선택
*DTO 이름이 DTO 로 끝나는 클래스만 선택
BaseDTO+ 클래스 이름 뒤에 '+'가 붙으면 해당 클래스로부터 파생된 모든 자식 클래스 선택, 인터페이스 이름 뒤에 '+'가 붙으면 해당 인터페이스를 구현한 모든 클래스 선택

 

(6) 메소드 지정

// 메서드 이름이 do 시작하고 파라미터가 2개인 모든 메서드
@Pointcut("execution(* do*(*, *))")

// server.spring 패키지 및 하위 패키지에 속해있고, 이름이 get으로 시작하는 파라미터가 0개 이상인 모든 메서드 
@Pointcut("execution(* server.spring..*.get*(..))")

 

표현식  설명
*(..) 모든 메소드 선택
update*(..) 메소드명이 update로 시작하는 모든 메소드 선택

 

(7) 파라미터 지정

// find로 시작하고 Long 유형의 매개변수가 하나만 있는 모든 메소드
@Pointcut("execution(* *..find*(Long))")

// 매개변수 수에 관계없지만, Long 유형의 첫 번째 매개변수를 가진 메소드 
@Pointcut("execution(* *..find*(Long,..))")
 

 

표현식  설명
(..) 타입에 무관한 0개 이상의 매개변수
(*) 반드시 1개의 매개변수를 가지는 메소드만 선택
(server.spring.domain.user.model.User) 매개변수로 User를 가지는 메소드만 선택. 꼭 풀패키지명이 있어야함
(!server.spring.domain.user.model.User) 매개변수로 User를 가지지않는 메소드만 선택
(Integer, ..) 한 개 이상의 매개변수를 가지되, 첫번째 인수는 Integer 타입으로 시작하고 나머지는 타입 무관
(Integer, *) 반드시 두 개의 매개변수를 가지되, 첫 번째 매개변수의 타입이 Integer인 메소드만 선택

 


2. execution 명시자  

execution ([접근제한자 패턴] [리턴 타입] [타입패턴 .] [이름패턴](파라미터 타입) [throws 예외패턴 ])
execution(* aspects.trace.demo.*.*(..))

 

1. 접근 제한자 패턴 : public, private 등 (생략 가능)

2. 리턴타입

3. 타입 패턴 : 패키지와 클래스 이름에 대한 패턴, '.'을 사용해 연결한다. (클래스 이름은 풀 패키지명으로 명시. 생략 가능)

4. 이름 패턴 : 메서드 이름 패턴 

5. 파라미터 : 파라미터의 타입패턴. 와일드 카드를 이용해 파라미터의 개수에 상관없는 패턴을 만들 수 있다.

 

와일드 카드 

@Pointcut("execution(* server.spring.service.BoardService.*(..))")

- 첫 번째 와일드 카드: 모든 반환 값과 일치

- 두 번째 와일드 카드: 모든 메서드 이름과 일치

- 세 번째 와일드 카드:  (..) => 모든 타입의 파라미터 0개 이상

 

 

3. within 명시자  

// com.baeldung 패키지나 하위 패키지 내의 모든 유형과 일치
@Pointcut("within(com.baeldung.pointcutadvice.dao.FooDao)")

// com.baeldung 패키지나 하위 패키지 내의 모든 유형과 일치
@Pointcut("within(com.baeldung..*)")

// server.spring 패키지의 모든 메서드
@Pointcut("within(server.spring*)")

 

 

4. bean 명시자  

// bean 이름이 userService 인 빈의 모든 메서드
@Pointcut("bean(userService)")

// bean 이름이 user 으로 시작하는 빈의 모든 메서드
@Pointcut("bean(user*)")

 

 

 

4. 포인트컷 표현식 결합  

 && , || ,

@Pointcut("@target(org.springframework.stereotype.Repository)")
public void repositoryMethods() {}

@Pointcut("execution(* *..create*(Long,..))")
public void firstLongParamMethods() {}

@Pointcut("repositoryMethods() && firstLongParamMethods()")
public void entityCreationMethods() {}

 

 

 

 

 

참고

https://sjh836.tistory.com/157

https://icarus8050.tistory.com/8

https://www.baeldung.com/spring-aop-pointcut-tutorial

https://docs.spring.io/spring-framework/reference/core/aop/ataspectj/pointcuts.html