对于最新的稳定版本,请使用 Spring Framework 6.2.0spring-doc.cn

Spring 中的 Pointcut API

本节描述了 Spring 如何处理关键的切入点概念。spring-doc.cn

概念

Spring 的切入点模型支持独立于通知类型的切入点重用。您可以 使用相同的切入点定位不同的建议。spring-doc.cn

interface 是中央接口,用于 将 Advice 定位到特定的类和方法。完整的界面如下:org.springframework.aop.Pointcutspring-doc.cn

public interface Pointcut {

	ClassFilter getClassFilter();

	MethodMatcher getMethodMatcher();
}

将接口拆分为两部分允许重用类和方法 匹配部分和精细组合操作(例如执行 “union” 替换为另一个方法 matcher)。Pointcutspring-doc.cn

该接口用于将切入点限制为一组给定的目标 类。如果该方法始终返回 true,则所有目标类都是 匹配。下面的清单显示了接口定义:ClassFiltermatches()ClassFilterspring-doc.cn

public interface ClassFilter {

	boolean matches(Class clazz);
}

界面通常更重要。完整的界面如下:MethodMatcherspring-doc.cn

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)matchestrueisRuntime()truespring-doc.cn

大多数 implementations 是静态的,这意味着它们的方法 返回。在这种情况下,永远不会调用三参数方法。MethodMatcherisRuntime()falsematchesspring-doc.cn

如果可能,请尝试将切入点设为静态,允许 AOP 框架缓存 创建 AOP 代理时的切入点评估结果。

对切入点的操作

Spring 支持对切入点进行操作(特别是 union 和 intersection)。spring-doc.cn

Union 表示任一切入点匹配的方法。 Intersection 表示两个切入点匹配的方法。 Union 通常更有用。 您可以通过使用类中的静态方法或在同一包中使用该类来编写切入点。但是,使用 AspectJ 切入点 表达式通常是一种更简单的方法。org.springframework.aop.support.PointcutsComposablePointcutspring-doc.cn

AspectJ 表达式切入点

从 2.0 开始,Spring 使用的最重要的切入点类型是 。这是一个切入点 使用 AspectJ 提供的库来解析 AspectJ 切入点表达式字符串。org.springframework.aop.aspectj.AspectJExpressionPointcutspring-doc.cn

有关支持的 AspectJ 切入点原语的讨论,请参见上一章spring-doc.cn

便利的切入点实现

Spring 提供了几个方便的切入点实现。您可以使用其中的一些 径直;其他的旨在在特定于应用程序的切入点中进行子类化。spring-doc.cn

静态切入点

静态切入点基于方法和目标类,不能考虑 方法的参数。对于大多数用法,静态切入点就足够了,而且是最好的。 Spring 只能在首次调用方法时对静态切入点进行一次求值。 之后,无需在每次方法调用时再次评估切入点。spring-doc.cn

本节的其余部分描述了一些静态切入点实现,这些实现是 包含在 Spring 中。spring-doc.cn

正则表达式切入点

指定静态切入点的一种明显方法是正则表达式。多个 AOP 除了 Spring 之外的框架使这成为可能。 是泛型常规 expression 切入点,该切入点使用 JDK 中的正则表达式支持。org.springframework.aop.support.JdkRegexpMethodPointcutspring-doc.cn

使用该类,您可以提供模式字符串列表。 如果其中任何一个匹配项,则切入点的计算结果为 。(因此, 生成的切入点实际上是指定模式的并集。JdkRegexpMethodPointcuttruespring-doc.cn

以下示例演示如何使用:JdkRegexpMethodPointcutspring-doc.cn

<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 一起创建,如下例所示:RegexpMethodPointcutAdvisorAdviceAdviceJdkRegexpMethodPointcutRegexpMethodPointcutAdvisorspring-doc.cn

<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>

您可以与任何类型的设备一起使用。RegexpMethodPointcutAdvisorAdvicespring-doc.cn

属性驱动的切入点

一种重要的静态切入点类型是元数据驱动的切入点。这将使用 元数据属性的值(通常是源级元数据)。spring-doc.cn

动态切入点

动态切入点的评估成本高于静态切入点。他们考虑了 方法参数以及静态信息。这意味着他们必须 每次方法调用都会进行评估,并且结果不能被缓存,因为参数会 不同。spring-doc.cn

主要示例是切入点。control flowspring-doc.cn

控制流切入点

Spring 控制流切入点在概念上类似于 AspectJ 切入点, 虽然威力较弱。(目前无法指定切入点运行 在与另一个切入点匹配的连接点下方。控制流切入点与 当前调用堆栈。例如,如果连接点由方法 在 package 中或 by 类。控制流切入点 使用类指定。cflowcom.mycompany.webSomeCallerorg.springframework.aop.support.ControlFlowPointcutspring-doc.cn

控制流切入点在运行时的评估成本甚至比 其他动态切入点。在 Java 1.4 中,成本大约是其他动态的 5 倍 切入点。

切入点超类

Spring 提供了有用的切入点超类来帮助您实现自己的切入点。spring-doc.cn

因为静态切入点最有用,所以您可能应该子类 。这只需要实现一个 abstract 方法(尽管您可以覆盖其他方法来自定义行为)。这 以下示例显示如何 subclass :StaticMethodMatcherPointcutStaticMethodMatcherPointcutspring-doc.cn

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-doc.cn

自定义切入点

因为 Spring AOP 中的切入点是 Java 类而不是语言特性(如 AspectJ),你可以声明自定义切入点,无论是静态的还是动态的。习惯 Spring 中的切入点可以是任意复杂的。但是,我们建议使用 AspectJ 切入点 表达式语言(如果可以)。spring-doc.cn

Spring 的更高版本可能会提供对 JAC 提供的“语义切入点”的支持——例如,“更改目标对象中实例变量的所有方法”。