本节介绍 Spring 如何处理关键的切入点概念。
概念
Spring 的 pointcut 模型支持独立于建议类型的 pointcut 重用。您可以 使用相同的切入点针对不同的建议。
该接口是中央接口,用于
针对特定类别和方法提供有针对性的建议。完整的界面如下:org.springframework.aop.Pointcut
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
将接口拆分为两部分允许重用类和方法
匹配零件和细粒度合成操作(例如执行“并集”
使用另一个方法匹配器)。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 时,可以执行此评估
创建代理是为了避免对每个方法调用进行测试的需要。如果
two-argument 方法返回给定方法,MethodMatcher 的方法返回,three-argument matches 方法为
在每次方法调用时调用。这样可以有针对性地查看传递的参数
在目标建议开始之前立即调用方法。matches(Method, Class)
matches
true
isRuntime()
true
大多数实现都是静态的,这意味着它们的方法
返回。在这种情况下,从不调用三参数方法。MethodMatcher
isRuntime()
false
matches
如果可能,请尝试将 pointcuts 设置为静态,允许 AOP 框架缓存 创建 AOP 代理时的切点评估结果。 |
点切口上的操作
Spring 支持对切点的操作(特别是并集和相交)。
并集表示任一点切口匹配的方法。
相交表示两个切点匹配的方法。
联合通常更有用。
可以使用类中的静态方法或使用同一包中的类来编写切点。但是,使用 AspectJ pointcut
表达式通常是一种更简单的方法。org.springframework.aop.support.Pointcuts
ComposablePointcut
AspectJ 表达式切点
从 2.0 开始,Spring 使用的最重要的切入类型是 。这是一个切入点
使用 AspectJ 提供的库来分析 AspectJ 切入表达式字符串。org.springframework.aop.aspectj.AspectJExpressionPointcut
有关支持的 AspectJ 点切基元的讨论,请参阅上一章。
便利点切入实现
Spring 提供了几个方便的切入点实现。您可以使用其中的一些 径直;其他的则用于在特定于应用程序的切入点中进行子类化。
静态切点
静态切点基于方法和目标类,不能考虑 该方法的参数。对于大多数用法来说,静态切点就足够了,而且是最好的。 Spring 只能在首次调用方法时计算一次静态切入点。 之后,无需在每次方法调用时再次评估切点。
本节的其余部分将介绍一些静态切入点实现,这些实现是 包含在 Spring 中。
正则表达式切入点
指定静态切点的一种明显方法是正则表达式。几个AOP
除了 Spring 之外,其他框架使这成为可能。 是通用的常规
在 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 可以是拦截器,
抛出建议等)。在幕后,Spring 使用了 .
使用简化了接线,因为一个 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
Pointcut 超类
Spring 提供了有用的 pointcut 超类来帮助你实现自己的 pointcut。
由于静态切点最有用,因此您可能应该对 进行子类化。这只需要实现一个
abstract 方法(尽管您可以重写其他方法来自定义行为)。这
以下示例显示了如何子类化: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 提供的“语义切入”的支持,例如,“所有更改目标对象中实例变量的方法”。 |