2023. 5. 3. 16:04ㆍSpring Framework/Spring AOP APIs
이 섹션에서는 Spring이 중요한 포인트컷 개념을 어떻게 처리하는지 설명합니다.
Concepts
스프링의 포인트컷 모델은 advice 유형과 독립적으로 포인트컷을 재사용할 수 있게 해줍니다. 동일한 포인트컷으로 다양한 어드바이스를 타겟팅할 수 있습니다.
org.springframework.aop.Pointcut
인터페이스는 특정 클래스와 메서드를 타겟으로 어드바이스를 지정하기 위해 사용하는 핵심 인터페이스입니다. 전체 인터페이스는 다음과 같습니다:
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
Pointcut 인터페이스를 두 부분으로 나누면 클래스와 메서드 매칭 부분을 재사용하고, 세분화된 조합 작업(예: 다른 메서드 매처와 "합집합[union]" 수행)을 가능하게 합니다.
ClassFilter
인터페이스는 포인트컷을 특정 타겟 클래스 집합으로 제한하는 데 사용됩니다. matches()
메서드가 항상 true를 반환하면 모든 타겟 클래스가 일치합니다. 다음은 ClassFilter
인터페이스 정의입니다:
public interface ClassFilter {
boolean matches(Class clazz);
}
MethodMatcher
인터페이스가 일반적으로 더 중요합니다. 전체 인터페이스는 다음과 같습니다:
public interface MethodMatcher {
boolean matches(Method m, Class<?> targetClass);
boolean isRuntime();
boolean matches(Method m, Class<?> targetClass, Object... args);
}
matches(Method, Class)
메서드는 특정 클래스의 메서드가 포인트컷에 의해 일치하는지 여부를 테스트하는 데 사용됩니다. 이 평가를 AOP 프록시가 생성될 때 수행하여 모든 메서드 호출 시 테스트할 필요성을 없앨 수 있습니다. 만약 두 개의 아규먼트를 가지는 matches
메서드가 특정 메서드에 대해 true를 반환하고, MethodMatcher
의 isRuntime()
메서드가 true를 반환하면, 세 개의 아규먼트를 가지는 matches
메서드는 각 메서드 호출 시마다 호출됩니다. 이를 통해 포인트컷은 타겟 어드바이스가 시작되기 직전에 메서드 호출에 전달된 아규먼트를 검사할 수 있습니다.
대부분의 MethodMatcher
구현은 정적이어서 isRuntime()
메서드가 false를 반환합니다. 이 경우 세개의 아규먼트를 가지는 matches
메서드는 호출되지 않습니다.
가능하다면 포인트컷을 정적으로 만들어 AOP 프레임워크가 AOP 프록시가 생성될 때 포인트컷 평가 결과를 캐시할 수 있게 하는 것이 좋습니다.
MethodMatcher
인터페이스와 AOP에서의 역할
MethodMatcher
인터페이스는 스프링 AOP에서 메서드 단위로 포인트컷(Pointcut)을 정의할 때 사용되는 중요한 인터페이스입니다. 이 인터페이스는 특정 메서드가 포인트컷의 조건에 맞는지 여부를 결정합니다.
public interface MethodMatcher {
boolean matches(Method m, Class<?> targetClass);
boolean isRuntime();
boolean matches(Method m, Class<?> targetClass, Object... args);
}
메서드 설명
matches(Method m, Class<?> targetClass)
:- 역할: 이 메서드는 지정된 메서드(
m
)와 해당 메서드가 속한 클래스(targetClass
)가 포인트컷의 조건에 맞는지를 검사합니다. - 사용 시점: AOP 프록시가 생성될 때 한 번 실행됩니다. 이 메서드가
true
를 반환하면, 해당 메서드에 대해 어드바이스가 적용됩니다. - 장점: 정적 매칭(static matching)을 수행하므로, 메서드 호출 시마다 이 매칭 로직을 반복할 필요가 없습니다. 따라서 성능에 유리합니다.
- 역할: 이 메서드는 지정된 메서드(
isRuntime()
:- 역할: 이 메서드는 런타임 시점에서 추가적인 매칭 로직이 필요한지를 결정합니다.
- 반환 값:
true
를 반환하면, 메서드가 호출될 때마다 세 개의 아규먼트를 받는matches(Method m, Class<?> targetClass, Object... args)
메서드가 호출됩니다.false
를 반환하면, 메서드 호출 시 추가적인 매칭이 수행되지 않으며, 캐시된 결과를 사용합니다.
- 특징: 대부분의 구현에서는 정적 매칭이 더 효율적이므로
false
를 반환합니다.
matches(Method m, Class<?> targetClass, Object... args)
:- 역할: 이 메서드는
isRuntime()
이true
일 때만 호출되며, 메서드의 실제 아규먼트(args
)를 포함한 보다 세부적인 매칭을 수행합니다. - 사용 시점: 메서드 호출 시마다 실행되어, 특정 아규먼트 값에 따라 포인트컷 매칭 여부를 동적으로 결정할 수 있습니다.
- 성능 고려 사항: 런타임 매칭은 매 호출 시마다 실행되므로, 성능에 영향을 미칠 수 있습니다. 가능한 경우 정적 매칭을 선호하는 것이 좋습니다.
- 역할: 이 메서드는
정적 매칭과 런타임 매칭
1. 정적 매칭 (Static Matching)
- 설명: 정적 매칭은 AOP 프록시가 생성될 때 수행되는 매칭입니다. 즉, 애플리케이션이 시작되거나 빈이 초기화될 때 특정 메서드가 포인트컷에 일치하는지 미리 결정됩니다.
- 장점: 메서드 호출 시마다 매칭을 수행할 필요가 없기 때문에 성능이 더 좋습니다.
matches(Method m, Class<?> targetClass)
메서드에서 매칭이 수행되고, 그 결과는 캐시됩니다. - 적용 사례: 메서드 이름이나 메서드가 속한 클래스와 같은 고정된 특성에 따라 어드바이스를 적용할 때 사용됩니다.
2. 런타임 매칭 (Runtime Matching)
- 설명: 런타임 매칭은 메서드가 호출될 때마다 아규먼트 값과 같은 동적인 특성을 기반으로 매칭을 수행합니다. 이 경우, 매 호출 시마다
matches(Method m, Class<?> targetClass, Object... args)
메서드가 실행됩니다. - 단점: 매번 매칭이 수행되므로, 성능에 부정적인 영향을 미칠 수 있습니다.
- 적용 사례: 특정 아규먼트 값에 따라 어드바이스 적용 여부를 동적으로 결정해야 할 때 사용됩니다. 예를 들어, 메서드 아규먼트가 특정 값일 때만 로깅을 수행하도록 하는 경우가 있습니다.
포인트컷 캐싱의 중요성
- 캐싱의 이점: 포인트컷을 정적으로 만들어 AOP 프록시가 생성될 때 평가된 결과를 캐시하면, 메서드 호출 시 매칭을 다시 수행할 필요가 없어 성능이 개선됩니다. 캐싱된 결과를 사용하면 런타임 오버헤드를 줄일 수 있습니다.
- 결론: 가능하다면 정적 매칭을 활용하여 AOP 프레임워크가 효율적으로 동작하도록 하는 것이 좋습니다.
요약
- 정적 매칭: 성능에 유리하며, 대부분의 경우 사용됩니다.
- 런타임 매칭: 특정 상황에서만 사용하며, 성능에 영향을 줄 수 있습니다.
isRuntime()
: 런타임 매칭이 필요한지 여부를 결정합니다.- 캐싱: 정적 매칭 결과를 캐시하여 성능을 최적화할 수 있습니다.
이러한 설명을 바탕으로, 스프링 AOP에서 MethodMatcher
가 메서드 매칭을 어떻게 관리하고, 성능을 최적화하기 위해 어떻게 설계되어 있는지 이해할 수 있습니다.
Operations on Pointcuts
스프링은 포인트컷에 대한 작업(특히 합집합 및 교집합)을 지원합니다.
합집합은 두 포인트컷 중 하나라도 일치하는 메서드를 의미하고, 교집합은 두 포인트컷 모두에 일치하는 메서드를 의미합니다. 합집합이 일반적으로 더 유용합니다. 포인트컷을 구성하려면 org.springframework.aop.support.Pointcuts
클래스의 정적 메서드를 사용하거나 동일한 패키지에 있는 ComposablePointcut
클래스를 사용할 수 있습니다. 그러나 AspectJ 포인트컷 표현식을 사용하는 것이 보통 더 간단합니다.
AspectJ Expression Pointcuts
2.0 버전 이후, 스프링에서 가장 중요한 포인트컷 유형은 org.springframework.aop.aspectj.AspectJExpressionPointcut
입니다. 이는 AspectJ 포인트컷 표현식 문자열을 구문 분석하기 위해 AspectJ에서 제공하는 라이브러리를 사용하는 포인트컷입니다.
지원되는 AspectJ 포인트컷 프리미티브에 대한 논의는 이전 챕터를 참조하십시오.
Convenience Pointcut Implementations
스프링은 몇 가지 편리한 포인트컷 구현을 제공합니다. 이들 중 일부는 직접 사용할 수 있으며, 일부는 애플리케이션에 특화된 포인트컷에서 서브클래싱하기 위해 설계되었습니다.
Static Pointcuts
정적 포인트컷은 메서드와 타겟 클래스에 기반하며 메서드의 아규먼트를 고려할 수 없습니다. 대부분의 사용 사례에서 정적 포인트컷이 충분하며 최선의 선택입니다. 스프링은 메서드가 처음 호출될 때만 정적 포인트컷을 평가할 수 있습니다. 그 이후에는 각 메서드 호출 시마다 포인트컷을 다시 평가할 필요가 없습니다.
다음은 스프링에 포함된 몇 가지 정적 포인트컷 구현에 대한 설명입니다.
Regular Expression Pointcuts
정적 포인트컷을 지정하는 한 가지 명백한 방법은 정규 표현식을 사용하는 것입니다. 스프링 외의 여러 AOP 프레임워크도 이를 가능하게 합니다. org.springframework.aop.support.JdkRegexpMethodPointcut
은 JDK의 정규 표현식 지원을 사용하는 일반 정규 표현식 포인트컷입니다.
JdkRegexpMethodPointcut
클래스를 사용하면 패턴 문자열 목록을 제공할 수 있습니다. 이 중 하나라도 일치하면 포인트컷이 true로 평가됩니다. (결과적으로 지정된 패턴의 합집합이 되는 포인트컷이 생성됩니다.)
다음은 JdkRegexpMethodPointcut
을 사용하는 예제입니다:
<bean id="settersAndAbsquatulatePointcut"
class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="patterns">
<list>
<value>.*set.*</value>
<value>.*absquatulate</value>
</list>
</property>
</bean>
스프링은 RegexpMethodPointcutAdvisor
라는 편리한 클래스를 제공하여 어드바이스를 참조할 수 있게 해줍니다(조언은 인터셉터, 사전 조언, 예외 어드바이스 등일 수 있습니다). 내부적으로 스프링은 JdkRegexpMethodPointcut
을 사용합니다. RegexpMethodPointcutAdvisor
를 사용하면 하나의 빈이 포인트컷과 어드바이스를 모두 캡슐화하므로 연결이 간단해집니다. 다음은 이를 보여주는 예제입니다:
<bean id="settersAndAbsquatulateAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref bean="beanNameOfAopAllianceInterceptor"/>
</property>
<property name="patterns">
<list>
<value>.*set.*</value>
<value>.*absquatulate</value>
</list>
</property>
</bean>
RegexpMethodPointcutAdvisor
는 모든 어드바이스 유형과 함께 사용할 수 있습니다.
Attribute-driven Pointcuts
정적 포인트컷의 중요한 유형 중 하나는 메타데이터 기반 포인트컷입니다. 이는 메타데이터 속성(일반적으로 소스 수준 메타데이터)의 값을 사용합니다.
Dynamic pointcuts
동적 포인트컷은 정적 포인트컷보다 평가 비용이 더 많이 듭니다. 이들은 메서드 아규먼트뿐만 아니라 정적 정보를 고려합니다. 이는 메서드 호출 시마다 평가해야 하며, 아규먼트가 달라지므로 결과를 캐시할 수 없다는 것을 의미합니다.
주요 예는 control flow
포인트컷입니다.
Control Flow Pointcuts
스프링 제어 흐름 포인트컷은 개념적으로 AspectJ의 cflow
포인트컷과 유사하지만 덜 강력합니다. (현재는 다른 포인트컷에 의해 일치된 조인 포인트 아래에서 포인트컷을 실행하도록 지정할 방법이 없습니다.) 제어 흐름 포인트컷은 현재 호출 스택을 매칭합니다. 예를 들어, 조인 포인트가 com.mycompany.web
패키지의 메서드에 의해 호출되었거나 SomeCaller
클래스에 의해 호출된 경우 작동할 수 있습니다. 제어 흐름 포인트컷은 org.springframework.aop.support.ControlFlowPointcut
클래스를 사용하여 지정합니다.
제어 흐름 포인트컷은 다른 동적 포인트컷보다도 실행 시 평가 비용이 훨씬 더 비쌉니다. 자바 1.4에서는 그 비용이 다른 동적 포인트컷보다 약 5배 더 듭니다.
Pointcut Superclasses
스프링은 사용자 정의 포인트컷을 구현하는 데 유용한 포인트컷 슈퍼클래스를 제공합니다.
정적 포인트컷이 가장 유용하므로 StaticMethodMatcherPointcut
을 서브클래싱하는 것이 좋습니다. 이 경우 하나의 추상 메서드만 구현하면 되며(다른 메서드를 재정의하여 동작을 사용자 정의할 수 있음), 다음은 StaticMethodMatcherPointcut
을 서브클래싱하는 방법을 보여줍니다:
class TestStaticPointcut extends StaticMethodMatcherPointcut {
public boolean matches(Method m, Class targetClass) {
// 사용자 정의 기준에 맞는 경우 true 반환
}
}
'Spring Framework > Spring AOP APIs' 카테고리의 다른 글
Creating AOP Proxies Programmatically with the ProxyFactory (0) | 2024.11.17 |
---|---|
The Advisor API in Spring (0) | 2024.11.17 |
Advice API in Spring (0) | 2024.11.17 |
Using the ProxyFactoryBean to Create AOP Proxies (0) | 2023.05.16 |
Concise Proxy Definitions (0) | 2023.05.03 |