深入理解 SpringAOP(一):AOP 组件概述

概述

spring-aop 模块是 Spring 框架中最重要的组件之一,它为我们提供了强大的 AOP 功能,并为其他扩展功能(如声明式事务、声明式异步处理等)提供了支持。在本文中,我们将深入探讨 SpringAOP 的源码,从代理对象的创建开始,揭示 SpringAOP 的运行机制。

首先,在阅读这篇文章前,请先确保对 Spring 中 Bean 创建流程有基本的了解,因为实际上这个流程也是 SpringAOP 生效的关键。在这个基础上,我们将聚焦于 SpringAOP 中的后处理器,以及与 AOP 功能密切相关的通知器、通知和切点等组件或概念,通过对这些组件的代码结构深入认知,我们将更好地理解 SpringAOP 的内部工作原理。

当我们描述 AOP 的时候,它通常包含下述概念/组件:

  • 通知 Advice :是切面逻辑的具体实现,它决定了在切点处执行什么操作;
  • 切点 Pointcut:程序执行过程中的一个特定点,例如方法的调用或异常的抛出,它是通知的触发点;
  • 通知器 Advisor :它代表了要对哪些对象、在哪里、应用哪些通知,它通常是且不限于是通知和切点的组合体;
  • 连接点 Joinpoint :它代表了程序中的某一处位置,通常包含切点切入位置的一些信息,比如 MethodInvocationConstructorInvocation
  • 切面 Aspect:它是 AspectJ 的概念,在 Spring 中可以认为是一个同时包含多种 Advisor 的聚合体,实际使用时,我们通过 @Aspect 注解声明的切面中的方法会被转为多个 Advisor

接下来,我们将围绕着上述内容,展开研究。

本专题共三篇文章,这是第一篇:

  • 深入理解 SpringAOP(一):AOP 组件概述;
  • 深入理解 SpringAOP(二):AOP的执行流程;
  • 深入理解 SpringAOP(三):AspectJ支持;

一、通知器

因此,某种程度上来说,Advisor 就是某个具体切入规则的最小单位。

1、实现体系

image.png
通知器 Advisor 本身的方法异常简单,它只规定“要在哪里应用哪些通知”,而“对哪些类使用”则交由子类来实现:

public interface Advisor {
	
	// 获取通知操作,即具体的操作逻辑
	Advice getAdvice();

	// 每个切入目标是否都需要一个新的通知器
	boolean isPerInstance();

}

因此一般 Advisor 不会直接使用,而是转为具体的 PointcutAdvisorIntroductionAdvisor 使用。

2、切点通知器

PointcutAdvisor ,直译即切点通知器,允许通知器提供一个切点类 Pointcut ,用于匹配特定的方法或者类:

public interface PointcutAdvisor extends Advisor {

	// 获取切点,即类或方法匹配器
	Pointcut getPointcut();

}

它也是最常见的通知器,Spring 中大部分我们熟知的功能都基于它实现,比如用于处理 @Async 注解的 AsyncAnnotationAdvisor ,与用于处理 @Transcational 注解的 TransactionAttributeSourceAdvisor (严格来说这么说并不准确,因为实际上注解是由 TransactionAnnotationParser 处理的,不过这里我们认为它们相关)。

3、引介入通知器

IntroductionAdvisor ,直译即为引介通知器,比较少用到的通知器,用于实现接口引入——即让一个 bean 无中生有的获得特定某些接口的方法,有点类似于 kotlin 的扩展函数:

public interface IntroductionInfo {

	// 需要引入的接口,即被切入的类等于变相的实现了这些接口
	Class<?>[] getInterfaces();

}

它比较常用的实现应该是 DeclareParentsAdvisor ,用于配合 AspectJ@DeclareParents 做接口引入,不过确实不太常见,因此我们了解即可。

二、通知

image.png
Advice 即 “通知”,它表示切入对象后,需要“在什么地方做什么事”。它的子接口非常多,但是按切入位置可以简单分为三类:

  • 执行前通知:BeforeAdvice
  • 环绕通知:InterceptorAdvice
  • 后置通知:AfterAdvice ,这里又分为返回后通知 AfterReturningAdvice 和异常通知 ThrowsAdvice

比较有趣的是,除了 DynamicIntroductionAdvice 外,AdviceInterceptorBeforeAdviceAfterAdvice  这几个顶级接口都是没有抽象方法的标记接口,因此我们可以一般只关注具体的实现接口即可。
方法拦截器与切点
方法拦截器 MethodInterceptor 最常见的 Advice ,我们熟知的绝大部分基于 SpringAOP 提供的功能都依赖它实现——实际上,就算是其他的实现,到最后执行代理方法的时候依然要适配为 MethodInterceptor 去执行。

public interface MethodInterceptor extends Interceptor {

	// 拦截方法调用
	@Nullable
	Object invoke(@Nonnull MethodInvocation invocation) throws Throwable;

}

在这里,我们就会接触到 Joinpoint ,也就是切点的概念,MethodInvocation就是方法切点:
它包含了一次方法调用中的一些已知信息,包括调用的方法、调用的参数等等,最常见的实现是 ReflectiveInvocation ,我们在 AspectJ 中接触的 JoinPoint 跟它基本一样。
image.png

三、切点

切面 Pointcut 是属于 PointcutAdvisor 的一个组件,它用于匹配类或者方法:

public interface PointcutAdvisor extends Advisor {

	/**
	 * Get the Pointcut that drives this advisor.
	 */
	Pointcut getPointcut();
}

切点由类型过滤器 ClassFilter 和方法匹配器 MethodMatcher 两个组件共同组成:

public interface Pointcut {

	/**
	 * Return the ClassFilter for this pointcut.
	 * @return the ClassFilter (never {@code null})
	 */
	ClassFilter getClassFilter();

	/**
	 * Return the MethodMatcher for this pointcut.
	 * @return the MethodMatcher (never {@code null})
	 */
	MethodMatcher getMethodMatcher();

}

当使用时,将仅会拦截 ClassFilter  不过滤的类中与 MethodMatcher 匹配的方法。
比较常用的实现类为支持对类和方法名进行表达式匹配的 NameMatchMethodPointcut ,与支持 Spring 元注解机制,能够按照类和方法上注解进行匹配的 AnnotationMatchingPointcut

四、后处理器

image.png
AOP 发生在 Bean 的创建过程中,它基于特定的后处理器 AbstractAutoProxyCreator 完成,当然,实际上它的背后是一个大家族:
两个关键的抽象类

  • AbstractAutoProxyCreatorAbstractAutoProxyCreator是一个抽象类,实现了BeanPostProcessor接口,用于自动创建代理对象。它的作用是在Spring容器中自动检测符合条件的bean,并对其进行代理。它可以根据一些配置条件(例如bean的名称、类型、注解等)决定是否对目标bean进行代理,并提供了一些钩子方法供子类实现自定义的代理逻辑;
  • AbstractAdvisorAutoProxyCreatorAbstractAdvisorAutoProxyCreatorAbstractAutoProxyCreator 的子类,它进一步扩展了自动代理的功能。除了 AbstractAutoProxyCreator 的功能外,AbstractAdvisorAutoProxyCreator 还能够通过配置Advisor(通知器)来决定代理的行为;

两个关键的实现类

  • AspectJAwareAdvisorAutoProxyCreatorAspectJAwareAdvisorAutoProxyCreator 继承自 AbstractAdvisorAutoProxyCreator,它是Spring AOP的一个关键组件之一,用于实现基于AspectJ注解的自动代理。它支持使用AspectJ注解(如 @Aspect@Pointcut@Before@After 等)来定义切面,然后根据这些切面的定义,在目标 bean 上应用相应的通知;
  • AnnotationAwareAspectJAutoProxyCreatorAnnotationAwareAspectJAutoProxyCreatorAspectJAwareAdvisorAutoProxyCreator 的子类,它进一步扩展了 AspectJ 注解的自动代理功能。与 AspectJAwareAdvisorAutoProxyCreator 相比,AnnotationAwareAspectJAutoProxyCreator 提供了更加灵活的注解驱动的 AOP 配置方式。它支持使用 @Aspect 注解定义切面,并且还支持其他注解如 @Before@After@Around 等,用于在目标 bean 的方法上应用切面逻辑;

默认情况下,我们的项目都是基于 AnnotationAwareAspectJAutoProxyCreator 实现的 AOP 功能。
在后文,我们会深入后处理器的源码,从而跟踪 AOP 的运行流程。

总结

image.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章