概述
前面的博文介绍增强的时候,我们发现一个问题:增强被织入到了目标类的所有方法中.
如果我们希望有选择的织入目标类的某些特定方法中呢? ——–这个时候就需要使用切点进行目标连接点的定位。
描述连接点是进行AOP编程最主要的工作,我们来说下Spring AOP如何定位连接点。
增强提供了连接点方位信息,如织入到方法前面、后面等,而切点进一步描述了织入哪些类的哪些方法上
Spring通过org.springframework.aop.Pointcut接口描述切点,Pointcut由ClassFilter和MethodMatcher构成,它
通过ClassFilter定位到某个特定的类上,
通过MethodMatcher定位到某些特定方法上。
这样Pointcut就拥有了某些类的某些特定方法的能力。
ClassFilter中定义了唯一的方法
boolean matches(Class<?> clazz);
入参为一个被检测的类,该方法判断被检测的类是否匹配过滤条件。
Spring支持两种方法匹配器
静态方法匹配器
所谓静态方法匹配器,仅对方法名签名(包括方法名和入参类型及顺序)进行匹配。
动态方法匹配器
动态方法匹配器会在运行期方法检查入参的值。 静态匹配仅会判断一次,而动态匹配因为每次调用方法的入参可能不一样,所以每次调用方法都必须判断。
因此,动态匹配对性能的影响很大,一般情况下,动态匹配器不常用。 方法匹配器的类型由MethodMatcher接口的isRuntime方法的返回值决定, 返回false标识静态方法匹配器,true标识位动态方法匹配器。
六种切点类型
静态方法切点StaticMethodMatcherPointcut
org.springframework.aop.support.StaticMethodMatcherPointcut是静态方法切点的抽象基类,默认情况下匹配所有的类。
最常用的两个子类如上所示,分别是 NameMatchMethodPointcut 和 AbstractRegexpMethodPointcut , 前者提供简单字符串匹配方法签名,后者使用正则表达式匹配方法签名。
动态方法切点DynamicMethodMatcher
org.springframework.aop.support.DynamicMethodMatcher是动态方法切点的抽象基类,默认情况下匹配所有的类
注解切点AnnotationMatchingPointcut
org.springframework.aop.support.annotation.AnnotationMatchingPointcut实现类标识注解切点。 使用AnnotationMatchingPointcut支持在Bean中直接通过Java5.0注解标签定义切点
表达式切点ExpressionPointcut
org.springframework.aop.support.ExpressionPointcut接口主要是为了支持AspectJ切点表达式语法而定义的接口
流程切点ControlFlowPointcut
org.springframework.aop.support.ControlFlowPointcut实现类标识控制流程切点。 ControlFlowPointcut是一种特殊的切点,它根据程序执行堆栈的信息查看目标方法是否由某一个方法直接或间接发起调用,以此判断是否为匹配的连接点。
复合切点ComposablePointcut
org.springframework.aop.support.ComposablePointcut实现类是为了创建多个切点而提供的方便操作类。 它所有的方法都返回ComposablePointcut类,这样就可以使用链接表达式对切点进行操作,形如
Pointcut pc = new ComposalbePointcut().union(classFilter).intersection(methodMatcher).intersection(pointcut);
三种切面类型
由于增强包括横切代码,又包含部分连接点信息(方法前、方法后主方位信息),所以可以仅通过增强类生成一个切面。 但切点仅仅代表目标类连接点的部分信息(类和方法的定位),所以仅有切点无法制作出一个切面,必须结合增强才能制作出切面。
Spring使用org.springframework.aop.Advisor接口标识切面概念,一个切面同时包含横切代码和连接点信息。
切面可以分为3类:一般切面、切点切面、引介切面
我们来看下切面继承关系
一般切面Advisor
org.springframework.aop.Advisor代表一般切面,仅包含一个Advice
因为Advice包含了横切代码和连接点信息,所以Advice本身一个简单的切面,只不过它代表的横切的连接点是所有目标类的所有方法,因为这个横切面太宽泛,所以一般不会直接使用。
切点切面PointcutAdvisor
org.springframework.aop.PointcutAdvisor ,代表具有切点的切面,包括Advice和Pointcut两个类,这样就可以通过类、方法名以及方位等信息灵活的定义切面的连接点,提供更具实用性的切面。
PointcutAdvisor接口实现类
PointcutAdvisor主要有6个具体的实现类:
DefaultPointcutAdvisor
最常用的切面类型,它可以通过任意Pointcut和Advice定义一个切面,唯一不支持的就是引介的切面类型,一般可以通过扩展该类实现自定义的切面
NameMatchMethodPointcutAdvisor
通过该类可以定义按方法名定义切点的切面
RegexpMethodPointcutAdvisor
对于按照正则表达式匹配的方法名进行切点定义的切面,可以扩展该实现类进行操作。
AspectJExpressionPointcutAdvisor
用于AspectJ切点表达式定义切点的切面
StaticMethodMatcherPointcutAdvisor
静态方法匹配器切点定义的切面,默认情况下匹配所有的的目标类。
AspectJPointcutAdvisor
用于AspectJ语法定义切点的切面
这些Advisor的实现类都可以在Pointcut中找到对应物,实际上,他们都是通过扩展对应的Pintcut实现类并实现PointcutAdvisor接口进行定义的。
比如StaticMethodMatcherPointcutAdvisor
public abstract class StaticMethodMatcherPointcutAdvisor extends StaticMethodMatcherPointcut implements PointcutAdvisor, Ordered, Serializable
扩展了StaticMethodMatcherPointcut类并实现了PointcutAdvisor接口。
此外Advisor都实现了org.springframework.core.Ordered接口,Spring将根据Advisor定义的顺序决定织入切面的顺序。
引介切面IntroductionAdvisor
org.springframework.aop.IntroductionAdvisor代表引介切面, 引介切面是对应引介增强的特殊的切面,它应用于类层上面,所以引介切点使用ClassFilter进行定义。
静态普通方法名匹配切面
详情见另外一篇博文 Spring-AOP 静态普通方法名匹配切面
静态正则表达式方法匹配切面
详情见另外一篇博文 Spring-AOP 静态正则表达式方法匹配切面
动态切面
详情见另外一篇博文 Spring-AOP 动态切面
流程切面
详情见另外一篇博文 Spring-AOP 流程切面
复合切点切面
详情见另外一篇博文 Spring-AOP 复合切点切面
引介切面
详情见另外一篇博文 Spring-AOP 引介切面