WEB/Spring

스프링 핵심 원리 - 고급편 8) 포인트컷

Tony Lim 2022. 6. 13. 10:15
728x90

포인트컷 지시자

execution  , within ,args , this , target @target, @within , @annotation , @args , bean 들이 존재한다.

@Test
void printMethod() {
    //public java.lang.String hello.aop.member.MemberServiceImpl.hello(java.lang.String)
    log.info("helloMethod={}", helloMethod);
}

execution에 썼었던 regexp 같은것이 해당 주석이랑 매핑된다.

 

execution (접근제어자? 반환타입 선언타입?메서드이름(파리미터) 예외? ) 

? 는 생략할 수 있다는 의미

 

접근제어자? == public

반환타입 == java.lang.String

선언타입? == hello.aop.member.MemberServiceImpl

메서드이름 == hello

파라미터 == (java.lang.String)

 

pointcut.setExpression("execution(* *(..))");

필수 인것만 남긴것이다.

pointcut.setExpression("execution(* *el*(..))");

메서드이름에 앞뒤에 *을 넣은 것이다.

pointcut.setExpression("execution(* hello.aop.member.*.*(..))");

MemberServiceImpl , hello 가 *로 데체되었다.

pointcut.setExpression("execution(* hello.aop..*.*(..))");

하위 패키지 (자신포함) 을 표현하기위해  "aop.." 으로 표현할 수 있다.

pointcut.setExpression("execution(* hello.aop.member.MemberService.*(..))");

타입매칭이된다. execution에서 부모타입을 선언하면 자식클래스도 매칭이된다.

하지만 메소드의 경우에는 부모 클래스에 선언한 메소드만 매칭이된다. 자식 타입에만 존재하는 메서드는 매칭이 안된다.

//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();
}

 


 

this vs target

this == 스프링 빈으로 등록되어있는 프록시 객체를 대상으로 포인트컷을 매칭한다.

target == 실세 target 객체(실제 로직이 있는 객체) 를 대상으로 포인트컷을 매칭한다.

this(hello.aop.member.MemberServiceImpl) 으로 지정하면 proxy를 보고 판단하는데 memberServiceImpl을 찾을 수 없으로 AOP적용대상이 아니다.

this(hello.aop.member.MemberServiceImpl) 으로 하면 이번엔 proxy 안에 있음으로 AOP 적용대상이 된다.

//@SpringBootTest(properties = "spring.aop.proxy-target-class=false") //JDK 동적 프록시
@SpringBootTest(properties = "spring.aop.proxy-target-class=true") //CGLIB

테스트시 적용할 수 있는 옵션이다.

 

 

728x90