[SPRING 고급] 포인트컷 지시자
📍포인트컷 지시자
execution: 메서드 실행 조인 포인트를 매칭한다. 스프링 AOP에서 가장 많이 사용하고 기능도 복잡
within: 특정 타입 내의 조인 포인트를 매칭
args: 인자가 주어진 타입의 인스턴스인 조인 포인트
this: 스프링 빈 객체(스프링 AOP 프록시)를 대상으로 하는 조인 포인트
target: Target 객체(스프링 AOP 프록시가 가르키는 실제 대상)를 대상으로 하는 조인 포인트
@target: 실행 객체의 클래스에 주어진 타입의 애노테이션이 있는 조인 포인트
@within: 주어진 애노테이션이 있는 타입 내 조인 포인트
@annotation: 메서드가 주어진 어노테이션을 가지고 있는 조인 포인트를 매칭
@args: 전달된 실제 인수의 런타임 타입이 주어진 타입의 애노테이션을 갖는 조인 포인트
bean: 스프링 전용 포인트컷 지시자, 빈의 이름으로 포인트컷 지정
✔️ execution 파라미터 매칭 규칙
(String): 정확하게 String 타입 파라미터
(): 파라미터가 없어야 한다
(*): 정확히 하나의 파라미터, 단 모든 타입을 허용
(*, *): 정확히 두개의 파라미터, 단 모든 타입을 허용
(..): 숫자와 무관하게 모든 파라미터, 모든 타입을 허용. 참고로 파라미터가 없어도 된다
(String, ..): String 타입으로 시작해야 한다. 숫자와 무관하게 모든 파라미터, 모든 타입을 허용 ex. (String), (String, Xxx), (String, Xxx, Xxx)
✔️ within
within 지시자는 특정 타입 내의 조인 포인트에 대한 매칭을 제한한다.
그런데 within은 표현식에 부모 타입을 지정하면 안되고 정확하게 타입이 맞아야 한다.
✔️execution과 args의 차이점
execution은 파라미터 타입이 정확하게 매칭되어야 한다. execution은 클래스에 선언된 정보를 기반으로 판단한다.
args는 부모 타입을 허용한다. args는 실제 넘어온 파라미터 객체 인스턴스를 보고 판단한다
@target VS @within
@target은 인스턴스의 모든 메서드를 조인 포인트로 적용
@within은 해당 타입 내에 있는 메서드만 조인 포인트로 적용
쉽게 말해 @target은 부모 클래스의 메서드까지 어드바이스를 다 적용하고, @within은 자기 자신의 클래스에 정의된 메서드에만 어드바이스를 적용
🌟args, @args, @target과 같은 포인트컷 지시자는 단독으로 사용하면 안된다.
실행 시점에 일어나는 포인트컷 적용 여부도 결국 프록시가 있어야 실행 시점에 판단할 수 있다. 프록시가 없다면 판단 자체가 불가능하다. 그런데 스플이 컨테이너가 프록시를 생성하는 시점은 스프링 컨테이너가 만들어지는 애플리케이션 로딩 시점에 적용할 수 있다.
따라서 args, @args, @target 같은 포인트컷 지시자가 있으면 스프링은 모든 스프링 빈에 AOP를 적용하려고 시도한다.
프록시가 없으면 실행 시점에 판단 자체가 불가능하다.
문제는 이렇게 모든 스프링 빈에 AOP 프록시를 적용하려고 하면 스프링이 내부에서 사용하는 빈 중에는 final로 지정된 빈들도 이씨 때문에 오류가 발생할 수 있다. 따라서 이러한 표현식은 최대한 프록시 적용 대상을 축소하는 표현식과 함께 사용해야 한다.
@annotation
메서드가 주어진 애노테이션을 가지고 있는 조인 포인트를 매칭
@args
전달된 실제 인수의 런타임 타입이 주어진 타입의 애노테이션을 갖는 조인 포인트
📍this, target
this: 스프링 빈 객체(스프링 AOP 프록시)를 대상으로 하는 조인 포인트
target: Target 객체(스프링 AOP 프록시가 가르키는 실제 대상)를 대상으로 하는 조인 포인트
this, target은 적용 타입 하나를 정확하게 지정해야 한다