
execution
- 문법
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name- pattern(param-pattern) throws-pattern?) execution(접근제어자? 반환타입 선언타입?메서드이름(파라미터) 예외?)
- 메소드 실행 조인 포인트를 매칭한다.
?
는 생략할 수 있다.
*
같은 패턴을 지정할 수 있다.
*
은 아무 값이 들어와도 된다는 뜻이다.
- 파라미터에서
..
은 파라미터의 타입과 파라미터 수가 상관없다는 뜻이다.
예)
@Component
public class MemberServiceImpl implements MemberService {
@Override
public String hello(String param) {
return "ok";
}
public String internal(String param) {
return "ok";
}
}
- 가장 정확
- 접근제어자?: public
- 반환타입: String
- 선언타입?: hello.aop.member.MemberServiceImpl
- 메서드이름: hello
- 파라미터: (String)
- 예외?: 생략
@Test
void exactMatch() {
pointcut.setExpression("execution(public String hello.aop.member.MemberServiceImpl.hello(String))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
- 가장 생략
- 접근제어자?: 생략
- 반환타입: *
- 선언타입?: 생략
- 메서드이름: *
- 파라미터: (..)
- 예외?: 없음
@Test
void allMatch() {
pointcut.setExpression("execution(* *(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
- 메서드 이름 매칭
- 메서드 이름 앞 뒤에 * 을 사용해서 매칭할 수 있다.
@Test
void nameMatch() {
pointcut.setExpression("execution(* hello(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void nameMatchStar1() {
pointcut.setExpression("execution(* hel*(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void nameMatchStar2() {
pointcut.setExpression("execution(* *el*(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void nameMatchFalse() {
pointcut.setExpression("execution(* nono(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isFalse();
}
- 패키지 매칭
hello.aop.member.*(1).*(2)
.
: 정확하게 해당 위치의 패키지
..
: 해당 위치의 패키지와 그 하위 패키지도 포함
@Test
void packageExactMatch1() {
pointcut.setExpression("execution(* hello.aop.member.MemberServiceImpl.hello(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void packageExactMatch2() {
pointcut.setExpression("execution(* hello.aop.member.*.*(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void packageExactMatch3() {
pointcut.setExpression("execution(* hello.aop.*.*(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isFalse();
}
@Test
void packageMatchSubPackage1() {
pointcut.setExpression("execution(* hello.aop.member..*.*(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void packageMatchSubPackage2() {
pointcut.setExpression("execution(* hello.aop..*.*(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void typeExactMatch() {
pointcut.setExpression("execution(* hello.aop.member.MemberServiceImpl.*(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void typeSuperMatch() {
pointcut.setExpression("execution(* hello.aop.member.MemberService.*(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void typeMatchInternal() throws NoSuchMethodException {
pointcut.setExpression("execution(* hello.aop.member.MemberServiceImpl.*(..))");
Method internal = MemberServiceImpl.class.getMethod("internal", String.class);
Assertions.assertThat(pointcut.matches(internal, MemberServiceImpl.class)).isTrue();
}
@Test
void typeMatchNoSuperTypeMatchMethod() throws NoSuchMethodException {
pointcut.setExpression("execution(* hello.aop.member.MemberService.*(..))");
Method internal = MemberServiceImpl.class.getMethod("internal", String.class);
Assertions.assertThat(pointcut.matches(internal, MemberServiceImpl.class)).isFalse();
}
- 파라미터 매칭
(String)
: 정확하게 String 타입 파라미터
()
: 파라미터가 없어야 한다.
(*)
: 정확히 하나의 파라미터, 단 모든 타입을 허용한다.
(*, *)
: 정확히 두 개의 파라미터, 단 모든 타입을 허용한다.
(..)
: 숫자와 무관하게 모든 파라미터, 모든 타입을 허용한다. 참고로 파라미터가 없어도 된다. 0..* 로 이해하면 된다.
(String, ..)
: String 타입으로 시작해야 한다. 숫자와 무관하게 모든 파라미터, 모든 타입을 허용한다.
예) (String) , (String, Xxx) , (String, Xxx, Xxx)
허용
@Test
void argsMatch() {
pointcut.setExpression("execution(* *(String))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void argsMatchNoArgs() {
pointcut.setExpression("execution(* *())");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isFalse();
}
@Test
void argsMatchStar() {
pointcut.setExpression("execution(* *(*))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void argsMatchAll() {
pointcut.setExpression("execution(* *(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void argsMatchComplex() {
pointcut.setExpression("execution(* *(String, ..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}