[Spring] 포인트컷 표현식
2022. 8. 7. 22:07ㆍSpring/Spring AOP
포인트컷 지시자(Pointcut Designator)
- execution : 메소드 실행 조인 포인트를 매칭한다.
- within : 특정 타입 내의 조인 포인트를 매칭한다.
- args : 인자가 주어진 타입의 인스턴스인 조인 포인트
- this : 스프링 빈 객체를 대상으로 하는 조인 포인트
- target : Target 객체를 대상으로 하는 조인 포인트
- @target : 실행 객체의 클래스에 주어진 타입의 애노테이션이 있는 조인 포인트
- @within : 주어진 애노테이션이 있는 타입 내 조인 포인트
- @annotation : 메서드가 주어진 애노테이션을 가지고 있는 조인 포인트를 매칭
- @args : 전달된 실제 인수의 런타임 타입이 주어진 타입의 애노테이션을 갖는 조인 포인트
- bean : 스프링 전용 포인트컷 지시자, 빈의 이름으로 포인트컷을 지정한다.
execution : 가장 정교한 포인트컷을 만들 수 있다.
- execution(public String hg.community.member.MemberServiceImpl.register(String))
접근제어자 | 반환 타입 | 선언 타입 | 메서드 이름 | 파라미터 |
public | String | hg.community.member.MemberServiceImpl | register | (String) |
▷ 접근 제어자
- 생략 가능
▷ 반환 타입
* | 모든 리턴타입허용 |
void | 리턴타입 void인 메소드 선택 |
!void | void가 아닌 메소드 선택 |
String | 정확히 String이 리턴 타입인 메소드 선택 |
▷ 선언 타입
- 생략 가능
hg.community | 정확하게 패키지 선택 |
hg.community.. | 해당 위치의 패키지와 그 하위 패키지 모두 선택 |
hg.community..impl | hg.community로 시작하면서 마지막 패키지 이름이 Impl로 끝나는 패키지 선택 |
▷ 클래스명
MemberServiceImpl | 정확한 클래스 선택 |
*Impl | 이름이 Impl로 끝나는 클래스 선택 |
MemberService | 해당 클래스로 파생된 모든 자식 클래스 선택, 인터페이스 구현 된 모든 클래스 선택 (부모 타입을 선언해도 그 자식 타입이 매칭된다. |
- 이 때, 부모타입을 선택했을 경우 부모 타입에 있는 메서드만 매칭이 가능하고, 자식 타입의 메서드에 매칭을 시도하면 매칭에 실패하게 된다.
▷ 메소드명, 매개변수
* | 모든 메소드 선택 |
get*(..) | 이름이 get으로 시작하는 모든 메소드 선택 |
- 메서드 앞뒤로 *을 이용하여 매칭할 수 있다.
▷ 파라미터 매칭
(String) | 정확하게 String 타입 파라미터 |
() | 파라미터가 없어야 한다. |
(*) | 정확히 하나의 파라미터, but 모든 타입 허용 |
(*, *) | 정확히 두 개의 파라미터, but 모든 타입 허용 |
(..) | 파라미터의 개수도 타입도 상관없이 모두 허용(파라미터가 없는 경우도 매칭 가능) |
(String, ..) | String 타입으로 시작해야 한다. 이를 제외하면 모두 허용 |
within : 해당 타입이 매칭되면 그 안의 메서드(조인 포인트)들이 자동 매칭
within(hg.community.member.MemberServiceImpl)
- 이 경우 MemberServiceImpl 클래스의 메서드들이 자동으로 매칭된다.
- 그러나 execution과 차이점은 부모타입을 지정하면 안된다. 정확하게 타입이 맞아야 한다.
args : 인자가 주어진 타입의 인스턴스인 조인 포인트로 매칭
args(String) or args(java.io.Serializable) or args(Object)
- execution의 경우 파라미터 타입이 정확하게 맞아야 했던 반면, args는 부모 타입을 허용한다.
- String 메서드가 포함된 class를 매칭시킨다고 가정했을 때, execution 같은 경우에는 String으로 지정된 포인트컷만 매칭이 되었다면 args같은 경우는 위의 케이스 모두 매칭된다. (부모 타입을 허용하기 때문)
@Target : 인스턴스의 모든 메서드를 조인 포인트로 적용
@Within : 해당 타입 내의 메서드만 조인 포인트로 적용 (부모는 어드바이스 적용 X)
▷ 둘 모두 클래스 타입에 있는 어노테이션을 가지고 AOP 적용 여부를 판단한다.
@SpringbootTest 를 진행한다.
① 부모와 자식 객체 생성
@Autowired
Child child;
static class Parent {
public void parentMethod(){};
}
@ClassAop // 자식 클래스를 나중에 매칭시켜 주기 위한 어노테이션
static class Child extends Parent {
public void childMethod(){};
}
② Aspect를 만든다.
@Slf4j
@Aspect
static class AtTargetAtWithinAspect {
@Around("execution(* hello.aop..*(..)) && @target(hello.aop.member.annotation.ClassAop)")
public Object atTarget(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("@target {}", joinPoint.getSignature());
return joinPoint.proceed();
}
@Around("execution(* hello.aop..*(..)) && @within(hello.aop.member.annotation.ClassAop)")
public Object atWithin(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("@within {}", joinPoint.getSignature());
return joinPoint.proceed();
}
}
③ 스프링 빈으로 등록한다.
static class Config {
@Bean
public Parent parent() {
return new Parent();
}
@Bean
public Child child() {
return new Child();
}
@Bean
public AtTargetAtWithinAspect atTargetAtWithinAspect() {
return new AtTargetAtWithinAspect();
}
}
④ @Import를 통해 Config 클래스를 등록하고 test 진행
child.childMethod(); //부모, 자식 모두 있는 메서드
child.parentMethod(); //부모 클래스만 있는 메서드
@target void hg.community.springaop.AtTargetAtWithinTest$Child.childMethod()
@within void hg.community.springaop.AtTargetAtWithinTest$Child.childMethod()
@target void hg.community.springaop.AtTargetAtWithinTest$Parent.parentMethod()
- 위의 결과에서 볼 수 있듯, childMethod는 @target 이나 @within 둘의 매칭에 모두 성공한 것을 확인할 수 있으나, parentMethod의 경우에는 @within의 경우 매칭이 되지 않은 것을 확인할 수 있다.
- 이로써 알 수 있는 것은 @within은 해당 타입의 메소드만 매칭을 시키고 그 부모 타입의 메소드는 매칭시키지 않는다. 그러나, @target은 해당 인스턴스 내의 모든 메소드에 매칭을 시킨다.
'Spring > Spring AOP' 카테고리의 다른 글
[Spring] 스프링 AOP란? (0) | 2022.08.07 |
---|