Loading...
Spring Framework Reference Documentation 7.0.2의 Pointcut API in Spring의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
This section describes how Spring handles the crucial pointcut concept.
Spring의 pointcut model은 advice type과 무관하게 pointcut 재사용을 가능하게 합니다. 동일한 pointcut으로 서로 다른 advice를 target할 수 있습니다.
org.springframework.aop.Pointcut 인터페이스는 핵심 인터페이스로, 특정 클래스와 메서드에 advice를 target하는 데 사용됩니다. 전체 인터페이스는 다음과 같습니다:
1public interface Pointcut { 2 3 ClassFilter getClassFilter(); 4 5 MethodMatcher getMethodMatcher(); 6}
Pointcut 인터페이스를 두 부분으로 분리하면 클래스와 메서드 매칭 부분을 재사용할 수 있고, (다른 메서드 매처와 “union”을 수행하는 것과 같은) 세밀한 composition operation을 수행할 수 있습니다.
ClassFilter 인터페이스는 pointcut을 특정 target 클래스 집합으로 제한하는 데 사용됩니다. matches() 메서드가 항상 true를 반환하면 모든 target 클래스가 매치됩니다. 다음 목록은 ClassFilter 인터페이스 정의를 보여 줍니다:
1public interface ClassFilter { 2 3 boolean matches(Class clazz); 4}
MethodMatcher 인터페이스가 일반적으로 더 중요합니다. 전체 인터페이스는 다음과 같습니다:
1public interface MethodMatcher { 2 3 boolean matches(Method m, Class<?> targetClass); 4 5 boolean isRuntime(); 6 7 boolean matches(Method m, Class<?> targetClass, Object... args); 8}
matches(Method, Class) 메서드는 이 pointcut이 주어진 target 클래스의 특정 메서드에 대해 한 번이라도 매치되는지를 테스트하는 데 사용됩니다. 이 평가는 AOP 프록시가 생성될 때 수행될 수 있으며, 이를 통해 매 메서드 호출마다 테스트할 필요를 피할 수 있습니다.
인자가 두 개인 matches 메서드가 주어진 메서드에 대해 true를 반환하고, MethodMatcher의 isRuntime() 메서드가 true를 반환하면, 세 인자를 받는 matches 메서드가 매 메서드 호출 시마다 호출됩니다. 이를 통해 pointcut은 target advice가 시작되기 직전에 메서드 호출에 전달된 argument를 살펴볼 수 있습니다.
대부분의 MethodMatcher 구현은 static이며, 이는 그들의 isRuntime() 메서드가 false를 반환함을 의미합니다. 이 경우 세 인자를 받는 matches 메서드는 결코 호출되지 않습니다.
가능하다면 pointcut을 static으로 만들어, AOP 프레임워크가 AOP 프록시가 생성될 때 pointcut 평가 결과를 캐시할 수 있도록 하십시오.
Spring은 pointcut에 대한 연산을 지원합니다(특히 union과 intersection).
Union은 두 pointcut 중 어느 하나라도 매치되는 메서드를 의미합니다. Intersection은 두 pointcut 모두에 매치되는 메서드를 의미합니다. Union이 보통 더 유용합니다.
org.springframework.aop.support.Pointcuts 클래스의 static 메서드를 사용하거나 동일한 패키지의 ComposablePointcut 클래스를 사용하여 pointcut을 구성할 수 있습니다. 그러나 일반적으로 AspectJ pointcut expression을 사용하는 것이 더 간단한 접근 방식입니다.
2.0 이후, Spring에서 사용되는 가장 중요한 type의 pointcut은
org.springframework.aop.aspectj.AspectJExpressionPointcut입니다. 이는 AspectJ에서 제공하는 라이브러리를 사용하여 AspectJ pointcut expression 문자열을 파싱하는 pointcut입니다.
지원되는 AspectJ pointcut primitive에 대한 논의는 이전 chapter를 참조하십시오.
Spring은 여러 편리한 pointcut 구현을 제공합니다. 일부는 직접 사용할 수 있고, 다른 것들은 애플리케이션 특화 pointcut에서 서브클래싱하도록 설계되었습니다.
Static pointcut은 메서드와 target 클래스에 기반하며 메서드의 argument를 고려할 수 없습니다. Static pointcut은 대부분의 사용 사례에서 충분하며 — 그리고 가장 좋습니다.
Spring은 메서드가 처음 호출될 때 static pointcut을 한 번만 평가할 수 있습니다. 그 이후에는 매 메서드 호출마다 pointcut을 다시 평가할 필요가 없습니다.
이 section의 나머지 부분에서는 Spring에 포함된 몇 가지 static pointcut 구현에 대해 설명합니다.
Static pointcut을 지정하는 한 가지 명백한 방법은 정규 표현식입니다. Spring 외에도 여러 AOP 프레임워크가 이를 가능하게 합니다.
org.springframework.aop.support.JdkRegexpMethodPointcut은 JDK의 정규 표현식 지원을 사용하는 일반적인 정규 표현식 pointcut입니다.
JdkRegexpMethodPointcut 클래스를 사용하면 패턴 문자열의 리스트를 제공할 수 있습니다. 이들 중 하나라도 매치되면 pointcut은 true로 평가됩니다. (결과적으로, 생성된 pointcut은 지정된 패턴의 union과 사실상 동일합니다.)
다음 예제는 JdkRegexpMethodPointcut을 사용하는 방법을 보여 줍니다:
1@Configuration 2public class JdkRegexpConfiguration { 3 4 @Bean 5 public JdkRegexpMethodPointcut settersAndAbsquatulatePointcut() { 6 JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut(); 7 pointcut.setPatterns(".*set.*", ".*absquatulate"); 8 return pointcut; 9 } 10}
1@Configuration 2class JdkRegexpConfiguration { 3 4 @Bean 5 fun settersAndAbsquatulatePointcut() = JdkRegexpMethodPointcut().apply { 6 setPatterns(".*set.*", ".*absquatulate") 7 } 8}
1<bean id="settersAndAbsquatulatePointcut" 2 class="org.springframework.aop.support.JdkRegexpMethodPointcut"> 3 <property name="patterns"> 4 <list> 5 <value>.*set.*</value> 6 <value>.*absquatulate</value> 7 </list> 8 </property> 9</bean>
Spring은 RegexpMethodPointcutAdvisor라는 편의 클래스를 제공하며, 이를 통해 Advice도 함께 reference할 수 있습니다 (Advice는 interceptor, before advice, throws advice 등일 수 있음을 기억하십시오). 내부적으로 Spring은 JdkRegexpMethodPointcut을 사용합니다.
RegexpMethodPointcutAdvisor를 사용하면 하나의 빈이 pointcut과 advice를 모두 캡슐화하므로 wiring이 단순해집니다. 다음 예제에서 볼 수 있습니다:
1@Configuration 2public class RegexpConfiguration { 3 4 @Bean 5 public RegexpMethodPointcutAdvisor settersAndAbsquatulateAdvisor(Advice beanNameOfAopAllianceInterceptor) { 6 RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor(); 7 advisor.setAdvice(beanNameOfAopAllianceInterceptor); 8 advisor.setPatterns(".*set.*", ".*absquatulate"); 9 return advisor; 10 } 11}
1@Configuration 2class RegexpConfiguration { 3 4 @Bean 5 fun settersAndAbsquatulateAdvisor(beanNameOfAopAllianceInterceptor: Advice) = RegexpMethodPointcutAdvisor().apply { 6 advice = beanNameOfAopAllianceInterceptor 7 setPatterns(".*set.*", ".*absquatulate") 8 } 9}
1<bean id="settersAndAbsquatulateAdvisor" 2 class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> 3 <property name="advice"> 4 <ref bean="beanNameOfAopAllianceInterceptor"/> 5 </property> 6 <property name="patterns"> 7 <list> 8 <value>.*set.*</value> 9 <value>.*absquatulate</value> 10 </list> 11 </property> 12</bean>
RegexpMethodPointcutAdvisor는 어떤 Advice type과도 함께 사용할 수 있습니다.
중요한 type의 static pointcut 중 하나는 메타데이터 기반 pointcut입니다. 이는 메타데이터 attribute(일반적으로 소스 수준 메타데이터)의 값을 사용합니다.
Dynamic pointcut은 static pointcut보다 평가 비용이 더 많이 듭니다. 이들은 메서드 argument뿐만 아니라 static 정보도 고려합니다. 이는 매 메서드 호출마다 평가되어야 하며, argument가 달라지기 때문에 결과를 캐시할 수 없음을 의미합니다.
주요 예는 control flow pointcut입니다.
Spring control flow pointcut은 개념적으로 AspectJ cflow pointcut과 유사하지만, 덜 강력합니다. (현재로서는 다른 pointcut에 의해 매치된 join point 아래에서 pointcut이 실행되도록 지정할 방법이 없습니다.) Control flow pointcut은 현재 호출 스택을 매치합니다.
예를 들어, join point가 com.mycompany.web 패키지의 메서드나 SomeCaller 클래스에 의해 호출된 경우에 동작할 수 있습니다. Control flow pointcut은 org.springframework.aop.support.ControlFlowPointcut 클래스를 사용하여 지정합니다.
Control flow pointcut은 런타임에 평가하는 비용이 다른 dynamic pointcut보다도 상당히 더 많이 듭니다. Java 1.4에서 그 비용은 다른 dynamic pointcut의 약 다섯 배 정도입니다.
Spring은 자체 pointcut을 구현하는 데 도움이 되는 유용한 pointcut 슈퍼클래스를 제공합니다.
Static pointcut이 가장 유용하므로, 아마도 StaticMethodMatcherPointcut을 서브클래싱해야 할 것입니다. 이는 하나의 abstract 메서드만 구현하면 되며(동작을 커스터마이즈하기 위해 다른 메서드를 오버라이드할 수도 있습니다), 다음 예제는 StaticMethodMatcherPointcut을 서브클래싱하는 방법을 보여 줍니다:
1class TestStaticPointcut extends StaticMethodMatcherPointcut { 2 3 public boolean matches(Method m, Class targetClass) { 4 // return true if custom criteria match 5 } 6}
1class TestStaticPointcut : StaticMethodMatcherPointcut() { 2 3 override fun matches(method: Method, targetClass: Class<*>): Boolean { 4 // return true if custom criteria match 5 } 6}
Dynamic pointcut을 위한 슈퍼클래스도 있습니다. 어떤 advice type과도 custom pointcut을 함께 사용할 수 있습니다.
Spring AOP에서 pointcut은 AspectJ에서처럼 language feature가 아니라 Java 클래스이므로, static이든 dynamic이든 custom pointcut을 선언할 수 있습니다. Spring의 custom pointcut은 임의로 복잡할 수 있습니다. 그러나 가능하다면 AspectJ pointcut expression language를 사용할 것을 권장합니다.
이후 version의 Spring은 JAC에서 제공하는 “semantic pointcut” — 예를 들어 “target 객체의 인스턴스 변수를 변경하는 모든 메서드” — 에 대한 지원을 제공할 수 있습니다.
Spring AOP APIs
Advice API in Spring