Spring AOP Pointcut 표현식 - args

목차

Pointcut 표현식 - args

args 는 메서드의 매개변수를 기준으로 AOP 를 적용

args는 메서드의 매개변수를 기준으로 매칭하기 위한 표현식입니다. 메서드의 매개변수 타입이나 값을 기준으로 특정 메서드에만 AOP를 적용할 수 있습니다.

테스트를 위한 객체

@ClassAop
@Component
public class MemberServiceImpl implements MemberService {

@Override
@MethodAop("test value")
public String hello(String param) {
return "ok";
}

private String internal(String param) {
return "ok";
}
}

args 를 이용해 적용 여부 판단

@BeforeEach
public void init() throws NoSuchMethodException {
helloMethod = MemberServiceImpl.class.getMethod("hello", String.class);
}

private AspectJExpressionPointcut pointcut(String expression) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(expression);
return pointcut;
}

@Test
void args() {
// 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
void argsVsExecution() {
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();
}
Share