6.1Pointcut API
本节介绍Spring如何处理关键的切入点概念。
6.1.1 概念
Spring的切入点模型支持独立于通知类型的切入点重用。你可以使用相同的切入点来通知不同的建议目标。
org.springframework.aop.Pointcut接口是一个中心接口,用于将通知定向到特定的类和方法。完整interface如下:
将Pointcut接口拆分为两部分允许重用类和方法匹配部分以及细粒度组合操作(例如,使用另一个方法匹配器执行“联合”)。
ClassFilter接口用于将切入点限制为一组给定的目标类。如果matches()方法始终返回true,则所有目标类都匹配。下面的列表显示ClassFilter接口定义:
MethodMatcher接口通常来说更加重要。完整的接口如下:
matches(method,class)方法用于测试此切入点是否与目标类上的给定方法匹配。当创建AOP代理时可以执行此评估,以避免对每个方法调用进行测试。如果两个参数匹配的方法对于给定的方法返回true,而methodMatcher的isRuntime()方法返回true,则在每次方法调用时都会调用三个参数匹配的方法。这允许切入点查看在执行目标通知之前立即传递给方法调用的参数。
大多数MethodMatcher实现是静态的,这意味着它们的isRuntime()方法返回false。在本例中,从不调用三个参数matches方法。
如果可能,尝试使切入点静态化,允许AOP框架在创建AOP代理时缓存切入点评估的结果。
6.1.2 Pointcuts的操作
Spring支持对切入点的操作(尤其是Union和intersection)。
Union是指切入点匹配任意一个方法。intersection表示切入点同时匹配的方法。Union通常更有用。你可以使用org.springframework.aop.support.Pointcuts类中的静态方法或在同一个包中使用ComposablePointcut类来撰写切入点。然而,使用AspectJ切入点表达式通常是一种更简单的方法。
6.1.3 AspectJ表达式Pointcuts
从2.0开始,Spring使用的最重要的切入点类型是org.springframework.aop.aspectj.AspectJExpressionPointcut。这是一个切入点,它使用AspectJ提供的库来分析AspectJ切入点表达式字符串。
有关支持的aspectj切入点原语的讨论,请参阅上一章。
6.1.4 方便的Pointcut实现
Spring提供了几个方便的切入点实现。你可以直接使用其中的一些。其他的则被用在特定于应用程序的切入点中进行子类化。
静态切入点
静态切入点基于方法和目标类,不能考虑方法的参数。静态切入点对于大多数使用来说是最好的。当第一次调用方法时,Spring只能计算一次静态切入点。之后,不需要对每个方法调用再次计算切入点。 本节的其余部分描述了Spring中包含的一些静态切入点实现。
正则表达式切入点
指定静态切入点的一个明显方法是正则表达式。除了Spring,还有几个AOP框架使这成为可能。org.springframework.aop.support.JdkRegexpMethodPointcut是一个通用的正则表达式切入点,它使用JDK中的正则表达式支持。
通过JdkRegexpMethodPointcut类,可以提供模式字符串的列表。如果其中任何一个匹配,则切入点的计算结果为true。(因此,结果实际上是这些切点的并集。)
下面的示例演示如何使用JdkRegexpMethodPointcut:
Spring提供了一个名为RegexpMethodPointcutAdvisor的方便类,它还允许我们引用一个Advice(请记住,Advice可以是拦截器,在建议、抛出建议和其他建议之前)。在这背后,Spring使用了JdkRegexpMethodPointcut。使用RegexpMethodPointcutAdvisor简化了连接,因为一个bean同时封装了pointcut和advice,如下示例所示:
你可以在任何Advice类型中使用RegexpMethodPointcutAdvisor。
属性驱动Pointcuts
一种重要的静态切入点类型是元数据驱动的切入点。这将使用元数据属性的值(通常是源级元数据)。
动态pointcuts
动态切入点的计算成本比静态切入点高。它们考虑了方法参数和静态信息。这意味着必须用每个方法调用对它们进行评估,并且不能缓存结果,因为参数会有所不同。
主要的例子是控制流切入点。
控制流切入点
Spring控制流切入点在概念上与AspectJ CFlow切入点相似,但功能较弱。(目前无法指定在与另一个切入点匹配的连接点下方执行切入点。)控制流切入点与当前调用堆栈匹配。例如,如果连接点是由com.mycompany.web包中的方法或SomeCaller类调用的,则它可能会激发。通常使用org.springframework.aop.support.ControlFlowPointcut类指定控制流切入点。
控制流切入点在运行时的计算成本比其他动态切入点都要高。在Java 1.4中,成本是其他动态切入点的五倍。
6.1.5 Pointcut 父类
Spring提供了有用的切入点超类来帮助你实现自己的切入点。
因为静态切入点最有用,所以你可能应该将StaticMethodMatcherPointCut子类化。这只需要实现一个抽象方法(尽管你可以重写其他方法来定制行为)。下面的示例显示如何将StaticMethodMatcherPointCut子类化:
还有动态切入点的超类。你可以对任何通知类型使用自定义切入点。
6.1.6 自定义Pointcuts
因为Spring AOP中的切入点是Java类,而不是语言特征(如AspectJ中),所以可以声明自定义切入点,无论是静态的还是动态的。Spring中的自定义切入点可以任意复杂。但是,如果可以的话,我们建议使用AspectJ切入点表达式语言。
Spring的较新版本可能支持jac-提供的“语义切入点”,例如,“所有更改目标对象中实例变量的方法”。
最后更新于