此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10! |
Spring 中的切入点 API
本节介绍 Spring 如何处理关键的切入点概念。
概念
Spring 的切入点模型支持独立于通知类型的切入点重用。您可以 用相同的切入点瞄准不同的建议。
这org.springframework.aop.Pointcut
interface 是中央接口,用于
针对特定类和方法的目标建议。完整界面如下:
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
拆分Pointcut
接口分为两部分,允许重用类和方法
匹配部件和细粒度组合作(例如执行“并集”
使用另一个方法匹配器)。
这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
对于给定的方法,并且isRuntime()
方法,MethodMatcher 返回true
,则三参数匹配方法是
在每个方法调用时调用。这允许切入点查看传递的参数
到目标通知开始前的方法调用。
最MethodMatcher
实现是静态的,这意味着它们的isRuntime()
方法
返回false
.在这种情况下,三参数matches
方法永远不会被调用。
如果可能,请尝试使切入点静态,允许 AOP 框架缓存 创建AOP代理时的切入点评估结果。 |
切入点的作
Spring 支持对切入点的作(特别是并集和交集)。
联合表示任一切入点匹配的方法。
交点是指两个切入点匹配的方法。
联合通常更有用。
您可以使用org.springframework.aop.support.Pointcuts
类或使用ComposablePointcut
类。但是,使用 AspectJ 切入点
表达式通常是一种更简单的方法。
AspectJ表达式切入点
从 2.0 开始,Spring 使用的最重要的切入点类型是org.springframework.aop.aspectj.AspectJExpressionPointcut
.这是一个切入点
使用 AspectJ 提供的库来解析 AspectJ 切入点表达式字符串。
有关支持的 AspectJ 切入点基元的讨论,请参阅上一章。
便利切入点实现
Spring 提供了几种方便的切入点实现。您可以使用其中的一些 径直;其他的则旨在在特定于应用程序的切入点中进行子类化。
静态切入点(Static Pointcuts)
静态切入点基于方法和目标类,不能考虑 方法的参数。对于大多数用途,静态切入点已经足够了,而且是最好的。 Spring 只能在首次调用方法时评估一次静态切入点。 之后,无需在每次方法调用时再次评估切入点。
本节的其余部分描述了一些静态切入点实现,这些实现是 包含在 Spring 中。
正则表达式切入点
指定静态切入点的一种明显方法是正则表达式。几个AOP
除了 Spring 之外的框架使这成为可能。org.springframework.aop.support.JdkRegexpMethodPointcut
是通用常规
使用 JDK 中正则表达式支持的表达式切入点。
使用JdkRegexpMethodPointcut
类,则可以提供模式字符串列表。
如果其中任何一个是匹配的,则切入点的计算结果为true
.(因此,
生成的切入点实际上是指定图案的并集。
以下示例演示如何使用JdkRegexpMethodPointcut
:
-
Java
-
Kotlin
-
Xml
@Configuration
public class JdkRegexpConfiguration {
@Bean
public JdkRegexpMethodPointcut settersAndAbsquatulatePointcut() {
JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
pointcut.setPatterns(".*set.*", ".*absquatulate");
return pointcut;
}
}
@Configuration
class JdkRegexpConfiguration {
@Bean
fun settersAndAbsquatulatePointcut() = JdkRegexpMethodPointcut().apply {
setPatterns(".*set.*", ".*absquatulate")
}
}
<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
简化了布线,因为 One Bean 封装了两者
切入点和建议,如以下示例所示:
-
Java
-
Kotlin
-
Xml
@Configuration
public class RegexpConfiguration {
@Bean
public RegexpMethodPointcutAdvisor settersAndAbsquatulateAdvisor(Advice beanNameOfAopAllianceInterceptor) {
RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor();
advisor.setAdvice(beanNameOfAopAllianceInterceptor);
advisor.setPatterns(".*set.*", ".*absquatulate");
return advisor;
}
}
@Configuration
class RegexpConfiguration {
@Bean
fun settersAndAbsquatulateAdvisor(beanNameOfAopAllianceInterceptor: Advice) = RegexpMethodPointcutAdvisor().apply {
advice = beanNameOfAopAllianceInterceptor
setPatterns(".*set.*", ".*absquatulate")
}
}
<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
.这只需要实现一个
abstract 方法(尽管您可以覆盖其他方法来自定义行为)。这
以下示例演示如何将子类化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 提供的“语义切入点”的支持——例如,“更改目标对象中实例变量的所有方法”。 |