【Spring6源码・AOP】AOP源码解析
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
上一篇《【Spring6源码・AOP】代理对象的创建》我们知道了代理是如何创建的那么它又是如何工作的呢
创建完代理对象之后最终会真正的执行我们的目标方法但是步入该方法会进入cglib代理类的拦截方法。
进入cglib代理类
进入拦截方法之后首先获取拦截器链 这里面就是我们切面类中定义的前置 后置 环绕的配置还有一个是默认的。
看看是如何获取这些拦截器的先从缓存里取如果缓存没有调用getInterceptorsAndDynamicInterceptionAdvice() 方法去获取。
步入getInterceptorsAndDynamicInterceptionAdvice() 方法首先获取切面相关的通知配置初始化拦截器List集合。
紧接着在这个方法中对advisors数组进行循环遍历进行处理。
首先判断当前方法是否和我们切点中配置的方法相匹配。
如果匹配则调用registry.getInterceptors方法将 advice 转化为 intercepter。
让我们看看是如何进行转换的步入registry.getInterceptors方法初始化拦截器集合获取Advice【切面相关的配置】对适配器进行循环找到符合的拦截器然后加入我们初始化好的拦截器List集合中
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
如果适配器支持解析出来的advice那么就会将advisor解析成拦截器就 是86行的代码adapter.getIntercepter()
步入adapter.getIntercepter()方法每个适配器都会对应自己的拦截器。
得到拦截器之后放到缓存中以供下次使用。
就此得到了想要的拦截器chain最后创建CglibMethodInvocation对象调用该对象的proceed()方法。
来看一下CglibMethodInvocation的proceed()方法。
最终来到如下方法最后调用184行代码去调用该拦截器
步入proceed()方法
调用其父类的proceed()方法
调用invoke()方法
继续…
go on…太深了
最后将我们所有的目标方法封住成一个Object数组作为参数
这里首先通过反射机制将方法设置为可以访问。
最后去调用invoke()方法
invoke()
最终根据我们的切面以及目标方法进行相关处理。
最后通过invoke0( )方法去调用本地方法进而去调用切面中around()方法。
调用aroud方法
在 p.proceed() 方法前的操作都执行完之后会调用该方法。
步入该proceed方法。。。省略若干调用。。。最终调用invoke()方法
注意一下这里this.interceptorsAndDymamicMethodMatchers这个缓存实际上存放了所有的和切面相关的拦截器并且在初始化的时候是按排序存放的环绕的前置、before、【目标方法】after、环绕的后置。
并且每次从缓存中取的时候索引都会+1这样就可以递归该方法而且可以按顺序调用每一个拦截器。
不信你看看
所以我们该执行before这个拦截器了进入上图的invoke()方法。
步入before()方法最终又到了这设置方法的访问权限再调用invoke。
最后还是调用了本地方法去调用了切面的before方法。
完成了before的操作才开始目标方法的调用
其实到这里我们就应该知道下一步应该会调用after这个拦截器在这个拦截器真正执行之前会调用目标方法
咱们来看看吧截图真麻烦…
如果此时当前拦截器索引和缓存中的 size-1 相等那么就会执行下面的方法
步入该方法
设置方法访问权限然后invoke
通过反射去调用我们的目标方法
然后就调用了我们的目标方法
最后执行finally中的方法。
最后调用本地方法。
调用after方法。不行了我得去吃饭了妈妈叫我吃饭了呜呜呜你们自己看看挺简单的。🆒溜了。。。。
退出after的拦截器before拦截器。。。。。。。。。
最后回到around方法中继续执行后面的操作
最后结束around拦截器
至于这个返回值返回的是目标方法的。
好了好了累死了好像有个问题没有写就是三级缓存相关的明天吧专门给三级缓存写一篇。
祝大家开心爱你们。♥♥♥
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |