[Spring] 포인트컷 표현식

2022. 8. 7. 22:07Spring/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