포인트컷 지시자
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
테스트시 적용할 수 있는 옵션이다.
'WEB > Spring' 카테고리의 다른 글
스프링 DB 1편 4) 스프링과 문제 해결 - 트랜잭션 (0) | 2022.06.16 |
---|---|
스프링 핵심 원리 - 고급편 9) 실전, 실무 주의 사항 (0) | 2022.06.13 |
스프링 핵심 원리 - 고급편 7) @Aspect AOP , 스프링 AOP 개념 (0) | 2022.06.12 |
스프링 핵심 원리 - 고급편 6) 빈 후처리기 (0) | 2022.06.09 |
스프링 핵심 원리 - 고급편 5) 스프링이 지원하는 프록시 (0) | 2022.06.09 |