티스토리 뷰
포인트컷 지시자
포인트컷 표현식은 execution
같은 포인트컷 지시자(Pointcut Designator)로 시작한다. 줄여서 PCD라 한다.
포인트컷 지시자 종류
execution
: 메소드 실행 조인 포인트를 매칭한다. 스프링 AOP에서 가장 많이 사용하고, 기능도 복잡하다.within
: 특정 타입 내의 조인 포인트를 매칭한다.args
: 인자가 주어진 타입의 인스턴스인 조인 포인트this
: 스프링 빈 객체(스프링 AOP 프록시)를 대상으로 하는 조인 포인트target
: Target 객체(스프링 AOP 프록시가 가르키는 실제 대상)를 대상으로 하는 조인 포인트@target
: 실행 객체의 클래스에 주어진 타입의 애노테이션이 있는 조인 포인트@within
: 주어진 애노테이션이 있는 타입 내 조인 포인트@annotation
: 메서드가 주어진 애노테이션을 가지고 있는 조인 포인트를 매칭@args
: 전달된 실제 인수의 런타임 타입이 주어진 타입의 애노테이션을 갖는 조인 포인트bean
: 스프링 전용 포인트컷 지시자, 빈의 이름으로 포인트컷을 지정한다.
여러 지시자 중, execution
을 가장 많이 사용하고, 나머지는 자주 사용하지 않는다. 따라서 execution
을 중점적으로 알아보자!
execution
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
AspectJExpressionPointcut
은 포인트컷 표현식을 처리해주는 클래스로써, 여기에 포인트컷 표현식을 지정하면 된다. AspectJExpressionPointcut
는 상위에 Pointcut
인터페이스를 가진다.
문법
execution(접근제어자? 반환타입 선언타입?메서드이름(파라미터) 예외?)
- 메소드 실행 조인 포인트를 매칭한다.
?
는 생략할 수 있다.*
같은 패턴을 지정할 수 있다.
가장 정확하게 매칭되는 표현식
@Test
void exactMatch() {
// helloMethod=public java.lang.String com.hyuuny.advanced.member.MemberServiceImpl.hello(java.lang.String)
pointcut.setExpression("execution(public String com.hyuuny.advanced.member.MemberServiceImpl.hello(String))");
assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
AspectJExpressionPointcut
에 pointcut.setExpression
을 통해서 포인트컷 표현식을 적용할 수 있다.pointcut.matches(메서드,대상 클래스)
를 실행하면, 지정한 포인트컷 표현식의 매칭 여부를 true
, false
로 반환한다.
매칭 조건
- 접근제어자?:
public
- 반환타입:
String
- 선언타입?:
com.hyuuny.advanced.member.MemberServiceImpl
- 메서드이름:
hello
- 파라미터:
(String)
- 예외?: 생략
가장 많이 생략한 포인트컷
@Test
void allMatch() {
pointcut.setExpression("execution(* *(..))");
assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
가장 많이 생략한 포인트컷이다.
매칭 조건
- 접근제어자?: 생략
- 반환타입:
*
- 선언타입?: 생략
- 메서드이름:
*
- 파라미터: (..)
- 예외?: 없음
패키지 매칭 관련 포인트컷
@Test
void packageExactMatch1() {
pointcut.setExpression("execution(* com.hyuuny.advanced.member.MemberServiceImpl.hello(..))");
assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void packageExactMatch2() {
pointcut.setExpression("execution(* com.hyuuny.advanced.member.*.*(..))");
assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void packageExactMatchFalse() {
pointcut.setExpression("execution(* com.hyuuny.advanced.*.*(..))");
assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isFalse();
}
@Test
void packageMatchSubPackage1() {
pointcut.setExpression("execution(* com.hyuuny.advanced.member..*.*(..))");
assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void packageMatchSubPackage2() {
pointcut.setExpression("execution(* com.hyuuny..*.*(..))");
assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
com.hyuuny.advanced.member.*(1).*(2)
: (1)타입, (2)메서드 이름.
: 정확하게 해당 위치의 패키지..
: 해당 위치의 패키지와 그 하위 패키지도 포함
타입 매칭 - 부모 타입 허용
@Test
void typeExactMatch() {
pointcut.setExpression("execution(* com.hyuuny.advanced.member.MemberServiceImpl.*(..))");
assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void typeMatchSuperType() {
pointcut.setExpression("execution(* com.hyuuny.advanced.member.MemberService.*(..))");
assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
typeExactMatch()
는 타입 정보가 정확하게 일치하기 때문에 매칭된다.execution
에서는 MemberService
처럼 부모 타입을 선언해도 그 자식 타입은 매칭된다.
다형성에서 부모타입 = 자식타입
이 할당 가능하다는 점을 떠올려보면 된다.
타입 매칭 - 부모 타입에 있는 메서드만 허용
@Test
void typeMatchInternal() throws NoSuchMethodException {
pointcut.setExpression("execution(* com.hyuuny.advanced.member.MemberServiceImpl.*(..))");
Method internalMethod = MemberServiceImpl.class.getMethod("internal", String.class);
assertThat(pointcut.matches(internalMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void typeMatchNoSuperTypeMethodFalse() throws NoSuchMethodException {
pointcut.setExpression("execution(* com.hyuuny.advanced.member.MemberService.*(..))");
Method internalMethod = MemberServiceImpl.class.getMethod("internal", String.class);
assertThat(pointcut.matches(internalMethod, MemberServiceImpl.class)).isFalse();
}
internal(String)
메서드는 MemberServiceImpl
에만 선언되어 있기 때문에 typeMatchInternal()
은 true
를 반환하지만, 부모 타입을 선언한 typeMatchNoSuperTypeMethodFalse
는 false
를 반환한다.
파라미터 매칭
// String 타입 파라미터 허용
// (String)
@Test
void argsMatch() {
pointcut.setExpression("execution(* *(String))");
assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void argsMatchNoArgs() {
pointcut.setExpression("execution(* *())");
assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isFalse();
}
// 정확히 하나의 파라미터 허용, 모든 타입 허용
// (Xxx)
@Test
void argsMatchStar() {
pointcut.setExpression("execution(* *(*))");
assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
// 숫자와 무관하게 모든 파라미터, 모든 타입 허용
// (), (Xxx), (Xxx, Xxx)
@Test
void argsMatchAll() {
pointcut.setExpression("execution(* *(..))");
assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
// String 타입으로 시작, 숫자와 무관하게 모든 파라미터, 모든 타입 허용
// (String), (String, Xxx), (String, Xxx, Xxx)
@Test
void argsMatchComplex() {
pointcut.setExpression("execution(* *(String, ..))");
assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
(String)
: 정확하게 String 타입 파라미터()
: 파라미터가 없어야 한다.(*)
: 정확히 하나의 파라미터, 단 모든 타입을 허용한다.(*, *)
: 정확히 두 개의 파라미터, 단 모든 타입을 허용한다.(..)
: 숫자와 무관하게 모든 파라미터, 모든 타입을 허용한다. 참고로 파라미터가 없어도 된다.0..*
로 이해하면 된다.(String, ..)
: String 타입으로 시작해야 한다. 숫자와 무관하게 모든 파라미터, 모든 타입을 허용한다.(String)
,(String, Xxx)
,(String, Xxx, Xxx)
허용
Reference
김영한. 스프링 핵심 원리 - 고급편. 인프런.
'Spring' 카테고리의 다른 글
[Spring Security] JWT (Json Web Token) (0) | 2022.07.21 |
---|---|
[Spring] AOP @target, @within (0) | 2022.06.06 |
[Spring] Advice 종류 (0) | 2022.05.29 |
[Spring] AOP 용어 (0) | 2022.05.25 |
[Spring] AOP는 어떻게 적용되는걸까? (0) | 2022.05.24 |
- Total
- Today
- Yesterday
- 데이터베이스
- 정렬
- 북클럽
- 스프링 부트
- MySQL
- 코테
- spring boot
- 노마드
- 김영한
- 자료구조
- Refactoring
- 파이썬
- leetcode
- 문자열
- 릿코드
- Real MySQL
- mysql 8.0
- webflux
- 리팩토링
- 노마드코더
- 구현
- 알고리즘
- kotlin
- 백준
- 스프링
- Spring
- 그리디
- 인프런
- Algorithm
- 코틀린
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |