|
对于最新的稳定版本,请使用 Spring Framework 7.0.6! |
Spring中的切点API
本节描述了Spring如何处理关键的切入点概念。
概念
Spring 的切入点模型使独立于通知类型的切入点重用成为可能。您可以使用相同的切入点针对不同的通知。
org.springframework.aop.Pointcut 接口是核心接口,用于将通知定向到特定的类和方法。完整的接口如下:
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
将 Pointcut 接口拆分为两部分允许重用类和方法匹配部分,并进行细粒度的组合操作(例如与另一个方法匹配器执行“并集”)。
The ClassFilter 接口用于将切点限制为给定的目标类集合。如果 matches() 方法始终返回 true,则匹配所有目标类。以下列出显示了 ClassFilter 接口定义:
public interface ClassFilter {
boolean matches(Class clazz);
}
The MethodMatcher 接口通常更重要。完整的接口如下:
public interface MethodMatcher {
boolean matches(Method m, Class<?> targetClass);
boolean isRuntime();
boolean matches(Method m, Class<?> targetClass, Object... args);
}
The matches(Method, Class) 方法用于测试此切入点是否曾经匹配目标类上的给定方法。此评估可以在创建 AOP 代理时执行,以避免每次方法调用都需要进行测试。如果两参数的 matches 方法返回 true 对于给定的方法,并且 isRuntime() 方法对于 MethodMatcher 返回 true,则在每次方法调用时都会调用三参数的 matches 方法。这使得切入点可以在目标通知开始之前立即查看传递给方法调用的参数。
大多数 MethodMatcher 实现是静态的,这意味着它们的 isRuntime() 方法
返回 false。在这种情况下,三参数的 matches 方法从未被调用。
| 如果可能,尽量使切入点静态化,这样可以让 AOP 框架在创建 AOP 代理时缓存切入点评估的结果。 |
切点操作
Spring 支持对切点的操作(特别是并集和交集)。
Union means the methods that either pointcut matches.
Intersection means the methods that both pointcuts match.
Union is usually more useful.
You can compose pointcuts by using the static methods in the
org.springframework.aop.support.Pointcuts class or by using the
ComposablePointcut class in the same package. However, using AspectJ pointcut
expressions is usually a simpler approach。
AspectJ 表达式切入点
自2.0版本以来,Spring使用的最重要的切入点类型是
org.springframework.aop.aspectj.AspectJExpressionPointcut。这是一种使用AspectJ提供的库来解析AspectJ切入点表达式字符串的切入点。
请参阅上一章以了解受支持的AspectJ切入点原语的讨论。
便捷的切点实现
Spring 提供了多种方便的切入点实现。你可以直接使用其中一些;其他则是为了在应用程序特定的切入点中被子类化而设计的。
静态切面
静态切点基于方法和目标类,不能考虑方法的参数。静态切点足以满足大多数使用场景,并且是最好的选择。Spring 只能在方法第一次被调用时评估一次静态切点。之后,每次方法调用时都不需要再次评估切点。
本节的其余部分描述了Spring中包含的一些静态切入点实现。
正则表达式切入点
一种明显的方式来指定静态切入点是使用正则表达式。除了Spring之外,有几个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>
Spring 提供了一个名为 RegexpMethodPointcutAdvisor 的便捷类,它让我们还可以引用一个 Advice(请记住,Advice 可以是拦截器、前置通知、抛出通知等)。在幕后,Spring 使用了一个 JdkRegexpMethodPointcut。使用 RegexpMethodPointcutAdvisor 简化了连线,因为一个 bean 封装了切入点和通知,如下例所示:
<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 与任何 Advice 类型。
切点超类
Spring 提供了有用的重点切面超类,帮助你实现自己的重点切面。
因为静态切入点最有用,你应该考虑继承StaticMethodMatcherPointcut。这只需要实现一个抽象方法(尽管你可以覆盖其他方法来定制行为)。以下示例展示了如何继承StaticMethodMatcherPointcut:
-
Java
-
Kotlin
class TestStaticPointcut extends StaticMethodMatcherPointcut {
public boolean matches(Method m, Class targetClass) {
// return true if custom criteria match
}
}
class TestStaticPointcut : StaticMethodMatcherPointcut() {
override fun matches(method: Method, targetClass: Class<*>): Boolean {
// return true if custom criteria match
}
}
还有动态切入点的超类。 您可以使用自定义切入点与任何通知类型。
自定义切入点
因为 Spring AOP 中的切入点是 Java 类而不是语言特性(如 AspectJ),所以你可以声明自定义切入点,无论是静态的还是动态的。Spring 中的自定义切入点可以非常复杂。但是,我们建议如果可能的话使用 AspectJ 的切入点表达式语言。
| Spring 的后续版本可能会提供对 JAC 提供的“语义切点”的支持——例如,“目标对象中更改实例变量的所有方法”。 |