@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
args
판단 시점
컴파일 시점 (정적)
런타임 시점 (동적)
타입 매칭
선언된 타입과 정확히 일치
상위 타입도 허용 (instanceof 방식)
주요 용도
메서드 시그니처 기반 포인트컷
파라미터 타입 기반 포인트컷, 파라미터 바인딩
/** * 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(); }
args 를 이용한 파라미터 바인딩
args 의 가장 강력한 기능 중 하나는 Advice 메서드에서 실제 전달된 파라미터 값을 직접 받아올 수 있다는 점입니다.
포인트컷 표현식에서 타입 대신 변수명을 작성하고, Advice 메서드의 파라미터와 이름을 맞추면 됩니다.