基于 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
方法开始入手。
通过advisor
的getAdvice
方法获取 Advice 对象的过程,是上一篇文章分析的主要内容,我们接着看后面的内容。
MethodInterceptor 的处理
if (adviceinstanceofMethodInterceptor) { interceptors.add((MethodInterceptor) advice); }
得到 Advice 之后,首先判断了它是不是 MethodInterceptor 接口的对象。我们看一下 MethodInterceptor 接口的定义。
publicinterfaceMethodInterceptorextendsInterceptor { 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#supportsAdvicepublicbooleansupportsAdvice(Adviceadvice) { return (adviceinstanceofMethodBeforeAdvice); }
supportsAdvice
方法的原理比较简单,就是判断当前要处理的 Advice 类型,是不是特定的 Advice 类型,如果是的话,表示当前的适配器能够适配这个类型的 Advice 对象。它主要的工作还是在getInterceptor方法中完成的。
// org.springframework.aop.framework.adapter.MethodBeforeAdviceAdapter#getInterceptorpublicMethodInterceptorgetInterceptor(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; } publicObjectinvoke(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
方法的下一个重要逻辑,就是增强逻辑的执行。