출처 : http://blog.naver.com/PostView.nhn?blogId=chocolleto&logNo=30086024618&categoryNo=29&viewDate=¤tPage=1&listtype=0
6. AspectJ의 Pointcut 표현식
□ POJO 클래스를 이용하여 AOP를 적용하는 두 가지 방법
- XML 스키마를 이용하여 Aspect를 설정하는 방법.
- @Aspect 어노테이션을 이용하여 Aspect를 설정하는 방법.
■ 두 방법의 공통점
- AspectJ의 문법을 이용하여 Pointcut을 설정.
■ <aop:태그>를 이용하여 Aspect를 설정하는 경우
- execution 명시자를 이용하여 Advice가 적용될 Pointcut을 설정.
<aop:aspect id="cacheAspect" ref="cache"> <aop:around method="read" pointcut="execution(public * kame.spring.chap03.core.*.readArticle(..))" /> </aop:aspect> |
□ AspectJ의 Pointcut 표현식
- AspectJ는 Pointcut을 명시할 수 있는 다양한 명시자를 제공.
- 스프링은 메서드 호출과 관련된 명시자만을 지원.
■ execution 명시자
- Advice를 적용할 메서드를 명시할 때 사용.
○ 기본 형식
execution(수식어패턴? 리턴타입패턴 패키지패턴?이름패턴(파라미터패턴) |
● 수식어 패턴
- 생략가능한 부분.
- public, protected 등이 옴.
● 리턴타입패턴
- 리턴 타입을 명시
● 클래스이름 패턴, 이름패턴
- 클래스 이름 및 메서드 이름을 패턴으로 명시.
● 파라미터패턴
- 매칭될 파라미터에 대해서 명시.
○ 특징
- 각 패턴은 '*'를 이용하여 모든 값을 표현.
- '..'을 이용하여 0개 이상이라는 의미를 표현.
○ 설정 예
● execution(public void set*(..))
- 리턴 타입이 void이고 메서드 이름이 set으로 시작하고, 파라미터가 0개 이상인 메서드 호출.
● execution(* kame.spring.chap03.core.*.*())
- kame.spring.chap03.core 패키지의 파라미터가 없는 모든 메서드 호출.
● execution(*.kame.spring.chap03.core..*.*(..))
- kame.spring.chap03.core 패키지 및 하위 패키지에 있는 파라미터가 0개 이상인 메서드 호출.
● execution(Integer kame.spring.chap03.core.WriteArticleService.write(..))
- 리턴 타입이 Integer인 WriteArticleService 인터페이스의 write() 메서드 호출.
● execution(* get*(*))
- 이름이 get으로 시작하고 1개의 파라미터를 갖는 메서드 호출.
● execution(* get*(*, *))
- 이름이 get으로 시작하고 2개의 파라미터를 갖는 메서드 호출.
● execution(* read*(Integer, ..))
- 메서드 이름이 read로 시작하고, 첫 번째 파라미터 타입이 Integer이며, 1개 이상의 파라미터를 갖는 메서드 호출.
■ within 명시자
- 메서드가 아닌 특정 타입에 속하는 메서드를 Pointcut으로 설정할 때 사용.
○ 설정 예
● within(kame.spring.chap03.core.WriteArticleService)
- WriteArticleService 인터페이스의 모든 메서드 호출.
● within(kame.spring.chap03.core.*)
- kame.spring.chap03.core 패키지에 있는 모든 메서드 호출.
● within(kame.spring.chap03.core..*)
- kame.spring.chap03.core 패키지 및 그 하위 패키지에 있는 모든 메서드 호출.
■ bean 명시자
- 스프링 2.5 버전부터 스프링에서 추가적으로 제공하는 명시자.
- 스프링 빈 이름을 이용하여 Pointcut을 정의.
- 빈 이름의 패턴을 갖는다.
○ 설정 예
● bean(writeArticleService)
- 이름이 writeArticleService인 빈의 메서드 호출.
● bean(*ArticleService)
- 이름이 ArticleServie로 끝나는 빈의 메서드 호출.
■ 표현식 연결
- 각각의 표현식은 '&&' 나 '||' 연산자를 이용하여 연결 가능.
○ @Aspect 어노테이션을 이용하는 경우
- '&&' 연산자를 사용하여 두 표현식을 모두 만족하는 Joinpoint에만 Advice가 적용.
@AfterThrowing( pointcut = "execution(public * get*()) && execution(public void set*(..))") public void throwingLogging() { ... } |
○ XML 스키마를 이용하여 Aspect를 설정하는 경우
- '&&'나 '||' 연산자를 사용.
<aop:pointcut id="propertyMethod" expression="execution(public * get*()) && execution(public void set*(..))" /> |
- XML 문서이기 때문에 값에 들어가는 '&&' '||'를 '&&'로 표현.
- 설정파일에서 '&&'나 '||' 대신 'and'와 'or'를 사용할 수 있도록 하고 있음.
<aop:pointcut id="propertyMethod" expression="execution(public * get*()) and execution(public void set*(..))" /> |
□ 프록시 구현 방식에 따른 execution 적용 차이
- Pointcut은 실제로 프록시가 구현하고 있는 인터페이스를 기준으로 Pointcut을 적용.
- 인터페이스를 구현하고 있는 대상 객체에 대해서 Pointcut을 정의하려면 인터페이스를 기준으로 Pointcut을 작성.
<aop:aspect id="cacheAspect" ref="cache"> <aop:around method="read" pointcut="execution(public * kame..core.ReadArticleServiceImpl.get*(..))" /> </aop:aspect> <bean id="readArticleService" class="kame.spring.chap03.core.ReadArticleServiceImpl" /> |
- ReadArticleServiceImpl 클래스가 ReadArticleService 인터페이스를 구현하고 있다면,
<aop:around>는 ReadArticleServiceImpl 클래스의 get으로 시작하는 메서드에 적용.
(<aop:around> 태그에서 명시한 Pointcut은 readArticleService 빈에는 적용되지 않음.)
- ReadArticleServiceImpl 클래스가 인터페이스를 구현하고 있지 않다면,
생성된 프록시는 ReadArticleServiceImpl 클래스를 상속받아 생성됨. (Pointcut은 readArticleService 빈에만 적용.)
[출처] 3. 스프링 AOP (AspectJ의 Pointcut 표현식)|작성자 외계인셩