对于最新的稳定版本,请使用 Spring Framework 6.2.0! |
Spring 中的 Pointcut API
本节描述了 Spring 如何处理关键的切入点概念。
概念
Spring 的切入点模型支持独立于通知类型的切入点重用。您可以 使用相同的切入点定位不同的建议。
interface 是中央接口,用于
将 Advice 定位到特定的类和方法。完整的界面如下:org.springframework.aop.Pointcut
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
将接口拆分为两部分允许重用类和方法
匹配部分和精细组合操作(例如执行 “union”
替换为另一个方法 matcher)。Pointcut
该接口用于将切入点限制为一组给定的目标
类。如果该方法始终返回 true,则所有目标类都是
匹配。下面的清单显示了接口定义:ClassFilter
matches()
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);
}
该方法用于测试此切入点是否曾经
匹配目标类上的给定方法。当 AOP
创建 proxy 是为了避免在每次方法调用时都需要进行测试。如果
两个参数的方法返回给定方法,并且 MethodMatcher 的方法返回 ,三个参数匹配方法是
在每次方法调用时调用。这允许切入点查看传递的参数
添加到紧接 Target 通知开始之前的方法调用。matches(Method, Class)
matches
true
isRuntime()
true
大多数 implementations 是静态的,这意味着它们的方法
返回。在这种情况下,永远不会调用三参数方法。MethodMatcher
isRuntime()
false
matches
如果可能,请尝试将切入点设为静态,允许 AOP 框架缓存 创建 AOP 代理时的切入点评估结果。 |
对切入点的操作
Spring 支持对切入点进行操作(特别是 union 和 intersection)。
Union 表示任一切入点匹配的方法。
Intersection 表示两个切入点匹配的方法。
Union 通常更有用。
您可以通过使用类中的静态方法或在同一包中使用该类来编写切入点。但是,使用 AspectJ 切入点
表达式通常是一种更简单的方法。org.springframework.aop.support.Pointcuts
ComposablePointcut
AspectJ 表达式切入点
从 2.0 开始,Spring 使用的最重要的切入点类型是 。这是一个切入点
使用 AspectJ 提供的库来解析 AspectJ 切入点表达式字符串。org.springframework.aop.aspectj.AspectJExpressionPointcut
有关支持的 AspectJ 切入点原语的讨论,请参见上一章。
便利的切入点实现
Spring 提供了几个方便的切入点实现。您可以使用其中的一些 径直;其他的旨在在特定于应用程序的切入点中进行子类化。
静态切入点
静态切入点基于方法和目标类,不能考虑 方法的参数。对于大多数用法,静态切入点就足够了,而且是最好的。 Spring 只能在首次调用方法时对静态切入点进行一次求值。 之后,无需在每次方法调用时再次评估切入点。
本节的其余部分描述了一些静态切入点实现,这些实现是 包含在 Spring 中。
正则表达式切入点
指定静态切入点的一种明显方法是正则表达式。多个 AOP
除了 Spring 之外的框架使这成为可能。 是泛型常规
expression 切入点,该切入点使用 JDK 中的正则表达式支持。org.springframework.aop.support.JdkRegexpMethodPointcut
使用该类,您可以提供模式字符串列表。
如果其中任何一个匹配项,则切入点的计算结果为 。(因此,
生成的切入点实际上是指定模式的并集。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 提供了一个名为 的便捷类,它允许我们
也引用 an(请记住,an 可以是拦截器,在通知之前,
throws advice 等)。在幕后,Spring 使用 .
Using 简化了布线,因为一个 bean 封装了
pointcut 和 advice 一起创建,如下例所示:RegexpMethodPointcutAdvisor
Advice
Advice
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
Advice
切入点超类
Spring 提供了有用的切入点超类来帮助您实现自己的切入点。
因为静态切入点最有用,所以您可能应该子类 。这只需要实现一个
abstract 方法(尽管您可以覆盖其他方法来自定义行为)。这
以下示例显示如何 subclass :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 提供的“语义切入点”的支持——例如,“更改目标对象中实例变量的所有方法”。 |