@Test voidargs() { // hello(String)과 매칭 assertThat(pointcut("args(String)") .matches(helloMethod, MemberServiceImpl.class)).isTrue(); // Object 는 String 의 상위 타입 assertThat(pointcut("args(Object)") .matches(helloMethod, MemberServiceImpl.class)).isTrue(); assertThat(pointcut("args()") .matches(helloMethod, MemberServiceImpl.class)).isFalse(); assertThat(pointcut("args(..)") .matches(helloMethod, MemberServiceImpl.class)).isTrue(); assertThat(pointcut("args(*)") .matches(helloMethod, MemberServiceImpl.class)).isTrue(); assertThat(pointcut("args(String,..)") .matches(helloMethod, MemberServiceImpl.class)).isTrue(); }
execution 과 args 의 차이점
execution 은 컴파일 시점에 적용 대상을 판단합니다. 따라서, 파라미터 타입이 정확하게 일치돼야 하며 클래스에 선언된 정보를 기반으로 AOP 를 적용합니다.
args 는 런타임 시점에 전달받은 객체를 대상으로 적용여부를 판단합니다. 따라서 전달 받은 객체가 캐스팅이 될 경우 다시 말해, 포인트 컷 표현식이 객체의 상위 타입인 경우 AOP 를 적용할 수 있습니다.
/** * execution(* *(java.io.Serializable)): 메서드의 시그니처로 판단 (정적) * args(java.io.Serializable): 런타임에 전달된 인수로 판단 (동적) */ @Test voidargsVsExecution() { assertThat(pointcut("args(String)") .matches(helloMethod, MemberServiceImpl.class)).isTrue(); // args 는 상위 타입도 허용합니다. // Serializable 는 String 의 상위 타입 assertThat(pointcut("args(java.io.Serializable)") .matches(helloMethod, MemberServiceImpl.class)).isTrue(); // Object 는 String 의 상위 타입 assertThat(pointcut("args(Object)") .matches(helloMethod, MemberServiceImpl.class)).isTrue();
// execution 은 정확하게 매칭돼야 한다. assertThat(pointcut("execution(* *(String))") .matches(helloMethod, MemberServiceImpl.class)).isTrue(); assertThat(pointcut("execution(* *(java.io.Serializable))") //매칭 실패 .matches(helloMethod, MemberServiceImpl.class)).isFalse(); assertThat(pointcut("execution(* *(Object))") //매칭 실패 .matches(helloMethod, MemberServiceImpl.class)).isFalse(); }