【Spring - AOP】 --- 目标方法调用流程核心源码解读


1 简诉 + 源码跟踪入口

上篇文章《【Spring - AOP】 — 目标对象增强核心源码解读》解读了spring-aop利用动态代理机制在目标对象创建+初始化过程中对其进行增强的核心源码。对代理模式有所了解的肯定知道,无论是静态代理还是动态代理,只要使用了代理模式,那目标对象里目标方法的调用将不再简简单单只是方法本身。本篇文章将主要探索一下被spring-aop代理的目标对象在被调用时的具体执行流程。
源码的跟踪入口为从IOC容器获取目标对象 —> 并拿着目标对象调用目标方法。如下图所示:
在这里插入图片描述


2 目标方法调用流程的骨架 + 获取方法拦截器链

从IOC容器里获取到的目标对象是被增强后的代理对象,当调用目标对象里的目标方法div时,并不会直接进入div方法,而是会进入到其代理方法intercept。intercept方法里的核心源码如下:
所在类:DynamicUnadvisedExposedInterceptor
在这里插入图片描述


通过通知获取到的当前方法的方法拦截器链如下图所示。可以看到所谓的方法拦截器链就是一个List,且List中方法拦截器的顺序与通知的顺序一致,均为 AfterThrowing -> AfterReturning -> After -> Around -> Before。 — 可以与上文《【Spring - AOP】 — 目标对象增强核心源码解读》进行对比 。
在这里插入图片描述


3 链式调用通知方法 — 责任链模式+递归

如2中图1所示,在拿到通过织入目标方法的通知转换后的方法拦截器链后,spring会拿着该这个方法拦截器链去调用各个通知方法和目标方法,其入口为:
所在类:DynamicUnadvisedExposedInterceptor

// We need to create a method invocation...  //源码第687行
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

那它底层到底是如何调用各个通知方法和目标方法的呢?又是怎样保证各个方法的先后顺序的呢?与我反复提到的通知的顺序和方法拦截器的顺序有没有关系呢?

要解决这些问题肯定还是得深入到源码中去探寻答案。其实说实话这一块的源码我反反复复地已经读了好多好多遍了,但是就是不知道该怎么把他通过文字的形式给展示出来,想了好久最后画了如下这样一幅图。我感觉至少我自己通过这幅图已经可以很清楚地明白spring-aop目标方法调用的核心原理了,当然回答上面几个问题肯定也不在话下了。
proceed()方法所在类ReflectiveMethodInvocation
在这里插入图片描述


上面这幅图我已经上传到github上了— 源码地址:https://github.com/nieandsun/spring-study


发布了189 篇原创文章 · 获赞 187 · 访问量 39万+

猜你喜欢

转载自blog.csdn.net/nrsc272420199/article/details/103487259