Spring 源码阅读 66:基于 JDK 的 AOP 代理如何获取拦截器链(4)- 将 Advice 封装为拦截器

简介: 【1月更文挑战第1天】本文分析了 Advice 被封装成 MethodInterceptor 的过程,Spring AOP 用到的五种 Advice 中,有些本身就是 MethodInterceptor 的实现类,而有些需要通过适配器的封装。


基于 Spring Framework v5.2.6.RELEASE

相关阅读:Spring 源码阅读 61:基于 JDK 动态代理的 AOP 代理回调方法 invoke 分析

接上一篇:Spring 源码阅读 65:基于 JDK 的 AOP 代理如何获取拦截器链(3)- 从 Advisor 获取 Advice

概述

上一篇分析了从 Advisor 中获取 Advice 的过程,在得到 Advice 对象之后,还需要将它封装成拦截器,才能最终交给 JdkDynamicAopProxy 的invoke回调方法来执行其中的增强逻辑。本文的主要内容就是分析如何将 Advice 封装成拦截器,为了内容连贯性,建议从之前的文章开始阅读。

封装拦截器

先从 DefaultAdvisorAdapterRegistry 的getInterceptors方法开始入手。

通过advisorgetAdvice方法获取 Advice 对象的过程,是上一篇文章分析的主要内容,我们接着看后面的内容。

MethodInterceptor 的处理

if (adviceinstanceofMethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}

得到 Advice 之后,首先判断了它是不是 MethodInterceptor 接口的对象。我们看一下 MethodInterceptor 接口的定义。

@FunctionalInterfacepublicinterfaceMethodInterceptorextendsInterceptor {
Objectinvoke(MethodInvocationinvocation) throwsThrowable;
}

它是一个函数式接口,包含了一个invoke方法,方法的参数对象是当前的目标方法调用。再上一步获取 Advice 的过程分析中可以知道,我们的到的 Advice 一共就 5 中,分别对应了切面配置中的五种增强类型,所以,这里可以看一下这五种类型的 Advice 哪些是实现了 MethodInterceptor 接口的。

从上面的类关系图中可以看到,AspectJAroundAdvice / AspectJAfterAdvice / AspectJAfterThrowingAdvice 三个类型的 Advice 是实现了 MethodInterceptor 接口的,因此,三个类型中也包含了invoke方法的实现,而其他两个没有。

结合getInterceptors方法的返回值类型是MethodInterceptor[],可以知道,实现了 MethodInterceptor 接口的 Advice 可以直接作为返回值数组中的元素,添加到结果数组中,因此,代码中也是这样做的,在if语句块中将其添加到了方法开头声明好的列表interceptors中。

非 MethodInterceptor 的处理

再看下一段逻辑。

for (AdvisorAdapteradapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
   }
}

先看一下for循环条件语句中的this.adapters是什么。

privatefinalList<AdvisorAdapter>adapters=newArrayList<>(3);
publicDefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(newMethodBeforeAdviceAdapter());
registerAdvisorAdapter(newAfterReturningAdviceAdapter());
registerAdvisorAdapter(newThrowsAdviceAdapter());
}

结合成员变量的初始化,和构造方法中的逻辑可以看到,adapters中包含了 3 个对象,从名字可以看出他们是 Advice 相关的适配器。

从类关系图中可以看到,它们都是 AdvicorAdapter 的实现类,接口中声明了两个方法,通过接口源码中的注释,可以大概了解这两个方法的作用。

  • supportsAdvice 方法用来判断,当前的 AdvisorAdapter 类型,是否适配参数中给定的 Advice。
  • getInterceptor 的作用是通过给定的 Advisor 对象,获取一个包含 Advisor 中增强逻辑的 MethodInterceptor。

这是一个很典型的适配器模式的逻辑。通过它们的supportsAdvice方法可以知道它们适配的 Advice 类型分别是什么。

  • MethodBeforeAdviceAdapter 适配 MethodBeforeAdvice
  • AfterReturningAdviceAdapter 适配 AfterReturningAdvice
  • ThrowsAdviceAdapter 适配 ThrowsAdvice

在五个增强类型对应的 Advice 类型中,只有两个属于上述被适配的类型,分别是:

  • AspectJMethodBeforeAdvice 实现了 MethodBeforeAdvice 接口
  • AspectJAfterReturningAdvice 实现了 AfterReturningAdvice 接口

而这两个正好是没有实现 MethodInterceptor 接口的两个,也就是说,通过这一步操作,所有类型的 Advice 就都处理完了。

再回到刚刚的代码中,如果adapters中的一个元素能够适配当前的 Advice 对象,那么通过getInterceptor方法得到的 MethodInterceptor 对象,会被添加到最终结果列表interceptors中。

AdviceAdapter 适配器的原理

因为适配器的工作原理都相似,因此,下面以其中之一 MethodBeforeAdviceAdapter 来分析其工作原理。

// org.springframework.aop.framework.adapter.MethodBeforeAdviceAdapter#supportsAdvice@OverridepublicbooleansupportsAdvice(Adviceadvice) {
return (adviceinstanceofMethodBeforeAdvice);
}

supportsAdvice方法的原理比较简单,就是判断当前要处理的 Advice 类型,是不是特定的 Advice 类型,如果是的话,表示当前的适配器能够适配这个类型的 Advice 对象。它主要的工作还是在getInterceptor方法中完成的。

// org.springframework.aop.framework.adapter.MethodBeforeAdviceAdapter#getInterceptor@OverridepublicMethodInterceptorgetInterceptor(Advisoradvisor) {
MethodBeforeAdviceadvice= (MethodBeforeAdvice) advisor.getAdvice();
returnnewMethodBeforeAdviceInterceptor(advice);
}

在getInterceptor方法中,先获取到 Advisor 的getAdvice方法。在上一篇分析中,我们知道了,这里的getAdvice方法是有缓存机制的,因此不会再将封装 Advice 的过程又执行一遍,而是从缓存中读取。得到的advice是 MethodBeforeAdvice 类型,也就是通过supportsAdvice判断过适配的类型。然后再将其封装成一个 MethodBeforeAdviceInterceptor 返回。

我们看一下 MethodBeforeAdviceInterceptor 的定义。

publicclassMethodBeforeAdviceInterceptorimplementsMethodInterceptor, BeforeAdvice, Serializable {
privatefinalMethodBeforeAdviceadvice;
publicMethodBeforeAdviceInterceptor(MethodBeforeAdviceadvice) {
Assert.notNull(advice, "Advice must not be null");
this.advice=advice;
   }
@OverridepublicObjectinvoke(MethodInvocationmi) throwsThrowable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
returnmi.proceed();
   }
}

可以看到 MethodBeforeAdviceInterceptor 是实现了 MethodInterceptor 接口的。其实它的作用就是对 MethodBeforeAdvice 进行封装,得到一个 MethodInterceptor。

分析完了 MethodBeforeAdviceInterceptor 之后,AfterReturningAdviceAdapter 的逻辑是相似的,就不重复分析了,唯一的区别就是invoke方法中的实现不同,分别对应的不同类型的增强逻辑的执行时机不同。

返回结果

以上,就走完了getInterceptors方法的所有流程,得到一个 MethodInterceptor 的数组,结合前几篇文章分析的获取拦截器链的过程,这些 MethodInterceptor 会最终返回到 JdkDynamicAopProxy 的invoke方法中,作为以下这样代码的结果。

// Get the interception chain for this method.List<Object>chain=this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

也就是这行代码所调用的获取拦截器链的逻辑,一共写了四篇分析,欢迎阅读。

总结

本文分析了 Advice 被封装成 MethodInterceptor 的过程,Spring AOP 用到的五种 Advice 中,有些本身就是 MethodInterceptor 的实现类,而有些需要通过适配器的封装。至此,查找拦截器链的过程分析完了,接下来会分析 JdkDynamicAopProxy 的invoke方法的下一个重要逻辑,就是增强逻辑的执行。

目录
相关文章
|
1月前
|
监控 Java 开发者
Spring AOP动态代理
Spring AOP动态代理
43 1
|
1月前
|
设计模式 Java Maven
Spring Aop 底层责任链思路实现-springaopdi-ceng-ze-ren-lian-si-lu-shi-xian
Spring Aop 底层责任链思路实现-springaopdi-ceng-ze-ren-lian-si-lu-shi-xian
35 1
|
3天前
|
前端开发 Java Spring
[AIGC] Spring Interceptor 拦截器详解
[AIGC] Spring Interceptor 拦截器详解
|
24天前
|
XML Java Maven
Spring之Aop的注解使用
Spring之Aop的注解使用
|
30天前
|
Java Spring
Spring 如何实现 AOP
Spring 如何实现 AOP
17 0
|
1月前
|
Java 编译器 程序员
Spring AOP 和 AspectJ 的比较
Spring AOP 和 AspectJ 的比较
37 0
|
1月前
|
NoSQL 关系型数据库 MySQL
Docker安装详细步骤及相关环境安装配置(mysql、jdk、redis、自己的私有仓库Gitlab 、C和C++环境以及Nginx服务代理)
Docker安装详细步骤及相关环境安装配置(mysql、jdk、redis、自己的私有仓库Gitlab 、C和C++环境以及Nginx服务代理)
224 0
|
1月前
|
Java Spring
【spring(三)】AOP总结
【spring(三)】AOP总结
|
5月前
|
Java 编译器 数据安全/隐私保护
自定义注解与AOP结合使用
自定义注解与AOP结合使用
59 0
|
6月前
|
Java 数据库连接 数据库
MyBatis与Spring集成&常用注解以及AOP和PageHelper分页插件整合
MyBatis与Spring集成&常用注解以及AOP和PageHelper分页插件整合
53 0