-
포인트컷 - execution스프링/스프링 AOP 2023. 9. 23. 17:47
execution의 매칭 조건
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?namepattern(param-pattern) throws-pattern?)
위의 코드가 포인트컷의 매칭 조건이다. ?가 붙은 것들은 생략을 할 수 있다.
pointcut.setExpression("execution(public String hello.aop.member.MemberServiceImpl.hello(String))");
아무것도 생략을 하지 않았을 때의 경우이다.
매칭 조건 - (?)가 붙은 것들은 생략 가능
접근제어자(?) : public
반환타입 : String
선언타입(?) : hello.aop.member.MemberServiceImpl
메서드이름 : hello
파라미터 : (String)
예외(?) : 생략
생략할 수 있는 것들을 모두 생략한 execution
pointcut.setExpression("execution(* *(..))");
반환타입, 메서드이름 : * - 아무 값이나 들어와도 된다는 뜻
파라미터 : (..) - 파라미터 타입과 수가 상관 없다는 뜻
1. 메서드 이름으로 매칭
pointcut.setExpression("execution(* *el*(..))");
메서드 이름 앞 뒤에 *을 넣을 수도 있는데, 이러한 경우에는 el이라는 글자가 들어간 메서드는 전부 포인트컷으로 지정한다는 뜻이다.
2. 패키지 경로로 매칭
2 - 1) 정확한 패키지 경로, 메서드 이름 지정
pointcut.setExpression("execution(* hello.aop.member.MemberServiceImpl.hello(..))");
패키지 경로를 정확하게 적어주면 이 패키지에 있는 특정 메서드만 포인트컷으로 지정된다.
hello.aop.member.타입.메서드이름 순으로 지정해야 한다.
2 - 2) * 사용
pointcut.setExpression("execution(* hello.aop.member.*.*(..))");
member 패키지에서 *을 사용하면 위와 같은 기능을 수행한다.
2 - 3) * 사용시 주의점
pointcut.setExpression("execution(* hello.aop.*.*(..))"); // 에러
위와 같은 포인트컷은 에러가 발생한다. 그 이유는 hello.aop.*.*은 패키지 레벨이 안맞기 때문이다.
하위 패키지를 모두 포함시키고 싶으면 .을 두개 붙이면 된다.
2 - 4) 서브 패키지까지 매칭
pointcut.setExpression("execution(* hello.aop.member..*.*(..))");
이렇게 해주면 member랑 member 하위가 전부 포인트컷으로 지정된다.
2 - 5) 서브 패키지까지 매칭(2)
pointcut.setExpression("execution(* hello.aop..*.*(..))");
aop 패키지에서 ..*을 붙여줘도 된다.
3. 타입 매칭
3.1) 부모타입 허용
pointcut.setExpression("execution(* hello.aop.member.MemberService.*(..))");
경로를 MemberServiceImpl이 아니라 부모타입인 인터페이스 MemberService 경로로 설정해도 된다. execution에서는 부모타입 = 자식타입이 할당된다.
3.2) 구현체에만 있는 메서드를 인터페이스로 접근시
pointcut.setExpression("execution(* hello.aop.member.MemberService.*(..))"); Method internalMethod = MemberServiceImpl.class.getMethod("internal", String.class); assertThat(pointcut.matches(internalMethod, MemberServiceImpl.class)).isTrue(); // 에러 - false임
MemberService에는 hello라는 메서드만 있고 internal이라는 메서드는 없다. 인터페이스에 선언한 메서드만 포인트컷으로 지정될 수 있기 때문에 MemberService.*으로 설정했을 때에는 되지 않는다.
4. 파라미터 매칭
@Override @MethodAop("test value") public String hello(String param) { return "ok"; }
위의 메서드는 파라미터에 String 타입의 param이 들어간다.
4 - 1) 파라미터 정확히 지정
pointcut.setExpression("execution(* *(String))");
파라미터를 넣는 괄호안에 String을 넣어주는 것이다. 파라미터에 String 타입 하나만 받을 때만 적용된다.
4 - 2) 파라미터 하나만 들어오는 경우
pointcut.setExpression("execution(* *(*))");
파라미터 괄호 안에 *을 넣으면 아무 타입의 파라미터가 들어와도 된다. 하지만 갯수는 무조건 하나만 들어와야 한다.
4 - 3) 모든 파라미터 허용
pointcut.setExpression("execution(* *(..))");
..을 넣어주면 숫자와 무관하게 모든 타입을 허용한다. 심지어 파라미터가 없어도 된다.
4 - 4) 4 - 2와 4 - 3의 복합
pointcut.setExpression("execution(* *(String, ..))");
파라미터의 첫 번째는 무조건 String이어야하며, 그 뒤에는 아무 파라미터가 와도 되고 없어도 되는 조건이다.
포인트컷 지시자의 종류
1. execution : 메소드 실행 조인 포인트를 매칭한다. 스프링 AOP에서 가장 많이 사용하고, 기능도 복잡하다.
2. within : 특정 타입 내의 조인 포인트를 매칭한다.
3. args : 인자가 주어진 타입의 인스턴스인 조인 포인트
4. this : 스프링 빈 객체(스프링 AOP 프록시)를 대상으로 하는 조인 포인트
5. target : Target 객체(스프링 AOP 프록시가 가르키는 실제 대상)를 대상으로 하는 조인 포인트
6. @target : 실행 객체의 클래스에 주어진 타입의 애노테이션이 있는 조인 포인트7. @within : 주어진 애노테이션이 있는 타입 내 조인 포인트
8. @annotation : 메서드가 주어진 애노테이션을 가지고 있는 조인 포인트를 매칭
9. @args : 전달된 실제 인수의 런타임 타입이 주어진 타입의 애노테이션을 갖는 조인 포인트
10. bean : 스프링 전용 포인트컷 지시자, 빈의 이름으로 포인트컷을 지정한다.포인트컷 지시자는 많은데 거의 execution만 사용된다. 그렇기 때문에 execution을 이용해서 포인트컷을 지정하는 방법을 정확하게 알고 있어야 원하는 메서드에 aop를 적용할 수 있다.
나머지는 꼭 필요하다 생각되는 시점에 나중에 공부하면 될 것 같다.
'스프링 > 스프링 AOP' 카테고리의 다른 글
재시도 AOP (0) 2023.09.23 어노테이션으로 AOP 사용 (0) 2023.09.23 어드바이스 종류 (0) 2023.09.22 어드바이스 순서 (0) 2023.09.22 @Pointcut - 포인트컷 분리 (0) 2023.09.22