개발놀이터

스프링 AOP - 포인트컷 본문

Spring/Spring

스프링 AOP - 포인트컷

마늘냄새폴폴 2022. 1. 24. 18:45

이 포스팅은 인프런 김영한 님의 스프링 핵심 원리 고급 편을 보고 각색한 포스팅입니다. 자세한 내용은 강의를 확인해주세요

 

 

지금부터 포인트컷 표현식을 포함한 포인트컷에 대해서 알아보자

 

스프링AOP에서 제공하는 포인트컷은 꽤 많다. 

 

1. execution

2. within

3. args

4. this

5. target

6. @target

7. @within

8. @annotation

9. @args

10. bean

 

우리는 이중에서 자주 사용되는 1. execution, 8. @annotation에 대해서 알아볼 것이다. 

 

execution


먼저 execution의 문법을 살펴보자

 

execution은 메서드 실행 조인 포인트를 매칭하기 때문에 메서드의 정보를 적어준다. 

 

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

-?는 생략할 수 있다.

-*같은 패턴을 지정할 수 있다. 

 

이제 하나씩 뜯어보자

 

접근제어자 : public private protected와 같은 접근지정자를 말한다.

반환타입 : 해당 메서드의 반환 타입이 무엇인지 적는 것이다. (String, Integer, Object)

선언타입 : 해당 메서드의 패키지를 적는다. 

메서드이름 : 해당 메서드의 이름을 적는다.

파라미터 : 메서드에 달려있는 파라미터의 정보를 적는다.

예외 : 해당 메서드의 예외를 적는다. 

 

Ex) "execution(public String hello.aop.member.MemberServiceImpl.hello(String))"

public : 접근제어자

String : 반환타입

hello.aop.member.MemberServiceImpl : 선언타입 (패키지이름)

hello : 메서드이름

String : 파라미터

예외 생략

 

 

변형

* (별) 을 이용한 패턴을 넣을 수도 있다. 

 

Ex) "execution(public String hello.aop.member.MemberServiceImpl.*(String))"

 

뜻 : 접근제어자가 public이고 반환타입이 String이며 패키지명이 hello.aop.member.MemberServiceImpl인 그아래 하위 모든 메서드중 파라미터 타입이 String인 것에 대해 어드바이스를 적용하겠다. 

 

cf) 아직 포인트컷, 어드바이스, 어드바이저에 대해 아리송하다면 해당 포스팅을 복습하고 오자

https://coding-review.tistory.com/97

 

포인트컷, 어드바이스, 어드바이저

이 포스팅은 인프런 김영한 님의 스프링 핵심 원리 고급 편을 보고 각색한 포스팅입니다. 자세한 내용은 강의를 확인해주세요 포인트컷 : 어디에 부가 기능을 적용할지, 어디에 부가 기능을 적

coding-review.tistory.com

*을 이용한 패턴에 이런 것도 가능하다.

 

Ex) "execution(public String hello.aop.member.MemberServiceImpl.*llo(String)

 

이렇게 되면 *llo인 hello가 적용대상이 된다. 

 

 

또한 파라미터 속성에 .. (점점) 을 사용할 수도 있다. 

 

파라미터 속성에 ..이 들어간다는 것은 파라미터가 아예 없는 메서드부터 여러개인 메서드까지 모두 어드바이스의 대상이 된다는 것이다. 

 

Ex) "execution(* *(..))"

 

뜻 : 반환타입이 어떤것이든 상관없으며 메서드이름이 어떤것이든 상관없고 파라미터로 어떤 값이 넘어와도 상관없다. 

 

즉 모든 메서드에 어드바이스를 적용하겠다. 라는 뜻

 

특징

execution에서는 부모 타입을 선언해도 자식 타입이 매칭된다. 다형성에서 부모타입 = 자식타입이 할당 가능하다는 점을 떠올려보면 된다.

 

즉, "execution(public String hello.aop.member.MemberService.hello(..))" 이렇게 사용해도 된다는 것이다. MemberService는 MemberServiceImpl에 부모이기 때문에 매칭이 가능하다.

 

하지만 부모에 선언되어있는 메서드만 매칭이 된다. 

 

이것이 무슨 말이냐하면 MemberService에 hello가 선언되어있고 MemberServiceImpl에 hello를 구현했다고 하면 hello만 가능하고 다른 MemberServiceImpl에만 있는 메서드는 매칭이 안된다는 것이다. 

 

 

execution는 파라미터 매칭 규칙이 있다. 

(String) : 정확하게 String 타입 파라미터만 매칭

() : 파라미터가 없는 메서드에 매칭

(*) : 정확히 하나의 파라미터에 매칭, 단 모든 타입을 허용한다.

(*, *) : 정확히 두개의 파라미터에 매칭, 단 모든 타입을 허용한다.

(..) : 숫자와 무관하게 모든 파라미터, 모든 타입을 허용한다. 참고로 파라미터가 없어도 된다.

(String, ..) : String 타입으로 시작해야 하고 숫자와 무관하게 모든 파라미터 모든 타입을 허용한다. ( Ex) (String, Integer) / (String, Object) / (String, Integer, Object) 등등..)

 

 

 

@annotation

@annotation은 메서드가 주어진 어노테이션을 가지고 잇는 조인 포인트를 매칭하는 것이다.

 

쉽게 얘기해서 매칭하고싶은 어노테이션이 있는 것만 어드바이스를 적용하고 싶을 때 사용한다.

 

Ex) @Trace라는 어노테이션을 만들고 @Trace 어노테이션이 붙어있는 메서드나 클래스에 한해서 로그를 찍을 것이다. 

 

문법

"@annotation(선언타입.어노테이션이름)"

 

선언타입 = 패키지명

 

Ex) "@annotation(hello.aop.member.annotation.MethodAop)"

 

 

참고) 파라미터 바인딩

파라미터 바인딩을 통해 해당 어노테이션의 값을 사용할 수 있다. 

        @Before("@annotation(annotation)")
        public void atAnnotation(JoinPoint joinPoint, MethodAop annotation) {
            log.info("[@annotation]{}, annotationValue={}", joinPoint.getSignature(), annotation.value());
        }

파라미터로 바인딩 했을 경우 선언타입 어노테이션이름을 적지 않아도 된다. 여기서 주의해야 할 점은 @annotation에 들어갈 값 (annotation) 과 파라미터 이름을 동일하게 맞춰줘야 한다. 

 

따라서 위의 예제는 아래의 예제와 같은 뜻이 된다.

        @Before("@annotation(hello.aop.member.annotation.MethodAop)")
        public void atAnnotation(JoinPoint joinPoint) {
            log.info("[@annotation]{}, annotationValue={}", joinPoint.getSignature(), annotation.value());
        }

파라미터 바인딩을 통해 어노테이션을 적으면 코드가 깔끔해짐과 동시에 어노테이션의 값을 사용할 수 있다는 장점이 있다. 

 

여기까지 자주 사용하는 포인트컷인 execution과 @annotation에 대해서 알아보았다. 다음 포스팅에선 앞서 배웠던 것으로 실전에서 사용할만한 예제를 만들어보겠다. 

'Spring > Spring' 카테고리의 다른 글

@Target, @Retention  (0) 2022.01.24
스프링 AOP - 실전 예제  (0) 2022.01.24
@Aspect  (0) 2022.01.20
빈 후처리기  (0) 2022.01.20
포인트컷, 어드바이스, 어드바이저  (0) 2022.01.19