AOP 포인트컷 - execution

박찬우·2024년 2월 17일
0

스프링

목록 보기
67/88

execution

  • 문법
    • execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name- pattern(param-pattern) throws-pattern?) execution(접근제어자? 반환타입 선언타입?메서드이름(파라미터) 예외?)
    • 메소드 실행 조인 포인트를 매칭한다.
    • ?는 생략할 수 있다.
    • * 같은 패턴을 지정할 수 있다.
  • * 은 아무 값이 들어와도 된다는 뜻이다.
  • 파라미터에서 .. 은 파라미터의 타입과 파라미터 수가 상관없다는 뜻이다.

예)

  • 비교 클래스
@Component
public class MemberServiceImpl implements MemberService {
    @Override
    public String hello(String param) {
        return "ok";
    }

    public String internal(String param) {
        return "ok";
    }
}
  • 가장 정확
    • 접근제어자?: public
    • 반환타입: String
    • 선언타입?: hello.aop.member.MemberServiceImpl
    • 메서드이름: hello
    • 파라미터: (String)
    • 예외?: 생략
    @Test
    void exactMatch() {
        //public java.lang.String hello.aop.member.MemberServiceImpl.hello(java.lang.String)
        pointcut.setExpression("execution(public String hello.aop.member.MemberServiceImpl.hello(String))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }
  • 가장 생략
    • 접근제어자?: 생략
    • 반환타입: *
    • 선언타입?: 생략
    • 메서드이름: *
    • 파라미터: (..)
    • 예외?: 없음
    @Test
    void allMatch() {
        // 전체
        pointcut.setExpression("execution(* *(..))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }
  • 메서드 이름 매칭
    • 메서드 이름 앞 뒤에 * 을 사용해서 매칭할 수 있다.
	@Test
    void nameMatch() {
        // hello 메서드 전체
        pointcut.setExpression("execution(* hello(..))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }

    @Test
    void nameMatchStar1() {
        // ~hel~ 메소드 전체
        pointcut.setExpression("execution(* hel*(..))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }

    @Test
    void nameMatchStar2() {
        // ~el~ 메소드 전체
        pointcut.setExpression("execution(* *el*(..))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }

    @Test
    void nameMatchFalse() {
        // nono 메소드만
        pointcut.setExpression("execution(* nono(..))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isFalse();
    }
  • 패키지 매칭
    • hello.aop.member.*(1).*(2)
      • (1): 타입
      • (2): 메서드 이름
    • . : 정확하게 해당 위치의 패키지
    • .. : 해당 위치의 패키지와 그 하위 패키지도 포함
	@Test
    void packageExactMatch1() {
        // MemberServiceImpl 클래스 안 hello 메소드
        pointcut.setExpression("execution(* hello.aop.member.MemberServiceImpl.hello(..))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }

    @Test
    void packageExactMatch2() {
        // member.클래스.메소드
        pointcut.setExpression("execution(* hello.aop.member.*.*(..))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }

    @Test
    void packageExactMatch3() {
        // aop.클래스.메소드
        pointcut.setExpression("execution(* hello.aop.*.*(..))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isFalse();
    }

    @Test
    void packageMatchSubPackage1() {
    	// member 하위 패키지 전체 메소드
        pointcut.setExpression("execution(* hello.aop.member..*.*(..))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }

    @Test
    void packageMatchSubPackage2() {
    	// aop 하위 패키지 전체 메소드
        pointcut.setExpression("execution(* hello.aop..*.*(..))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }
  • 타입 매칭
    @Test
    void typeExactMatch() {
        pointcut.setExpression("execution(* hello.aop.member.MemberServiceImpl.*(..))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }

    @Test
    void typeSuperMatch() {
        // 자식 타입을 부모 타입으로 해도 매칭이 성공함
        pointcut.setExpression("execution(* hello.aop.member.MemberService.*(..))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }

    @Test
    void typeMatchInternal() throws NoSuchMethodException {
        pointcut.setExpression("execution(* hello.aop.member.MemberServiceImpl.*(..))");
        Method internal = MemberServiceImpl.class.getMethod("internal", String.class);
        Assertions.assertThat(pointcut.matches(internal, MemberServiceImpl.class)).isTrue();
    }

    @Test
    void typeMatchNoSuperTypeMatchMethod() throws NoSuchMethodException {
        // 자식 타입을 부모 타입으로 해도 매칭이 성공함
        // 대신 부모 타입에 설정된 메소드까지만 됨
        // 자식 타입에 설정된 메소도는 매칭 되지 않음
        pointcut.setExpression("execution(* hello.aop.member.MemberService.*(..))");
        Method internal = MemberServiceImpl.class.getMethod("internal", String.class);
        Assertions.assertThat(pointcut.matches(internal, MemberServiceImpl.class)).isFalse();
    }
  • 파라미터 매칭
    • (String) : 정확하게 String 타입 파라미터
    • () : 파라미터가 없어야 한다.
    • (*) : 정확히 하나의 파라미터, 단 모든 타입을 허용한다.
    • (*, *) : 정확히 두 개의 파라미터, 단 모든 타입을 허용한다.
    • (..) : 숫자와 무관하게 모든 파라미터, 모든 타입을 허용한다. 참고로 파라미터가 없어도 된다. 0..* 로 이해하면 된다.
    • (String, ..) : String 타입으로 시작해야 한다. 숫자와 무관하게 모든 파라미터, 모든 타입을 허용한다.
      예) (String) , (String, Xxx) , (String, Xxx, Xxx) 허용
@Test
    void argsMatch() {
        // 전체메소드(String x)
        pointcut.setExpression("execution(* *(String))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }

    @Test
    void argsMatchNoArgs() {
        // 전체메소드()
        pointcut.setExpression("execution(* *())");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isFalse();
    }

    @Test
    void argsMatchStar() {
        // 전체메소드(x)
        pointcut.setExpression("execution(* *(*))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }

    @Test
    void argsMatchAll() {
        // 전체메소드(x, xx, ...)
        pointcut.setExpression("execution(* *(..))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }

    @Test
    void argsMatchComplex() {
        // 전체메소드(String x, ..)
        pointcut.setExpression("execution(* *(String, ..))");
        Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
    }
profile
진짜 개발자가 되어보자

0개의 댓글