拿到代理对象,如何调用增强方法

news/2025/3/26 3:48:13/文章来源:https://www.cnblogs.com/jock766/p/18792680

步骤1

前面已经创建了MathCal的代理对象了,我们在调用方法时加一个断点

这里返回的确实是代理对象,这个对象中保存了详细信息(增强器,原始对象等),我们进入bean.add(2, 10) 中,来到


org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor.intercept(Object, Method, Object[], MethodProxy)方法,


拦截目标方法的执行

根据ProxyFactory获得目标方法的拦截器链,如果没有拦截器链,就直接执行目标方法

如果有拦截器链,将需要执行的目标对象,目标方法,连接器链传入,创建一个CglibMethodInvocation对象并调用proceed()方法

那么拦截器链如何获取呢?我们进入this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)方法中

通过advisorChainFactory获得目标方法的拦截器链,进入this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass)

先创建一个list保存所有拦截器,可以看到,list创建时,已经初始化长度,这个长度就是通知方法的个数+一个默认通知,对于本案例就是5个。


之后又在循环遍历所有增强器,调用registry.getInterceptors(advisor);将其增强器包装为Interceptor[]拦截器,那么是如何包装的呢?

进入到其中查看,其实很简单,首先判断增强器是不是MethodInterceptor,如果是就直接加入到list中,


如果不是就使用增强器的适配器AdvisorAdapter将增强器转为MethodInterceptor,之后转为数组返回。


foreach循环完后就获得了拦截器链(每一个通知方法又被包装为拦截器,利用MethodInterceptor机制)


步骤2

获得了拦截器链,拦截器链是如何执行的呢?获得拦截器链后有new了一个CglibMethodInvocation并调用了proceed()方法

我们进入到proceed()方法

this.currentInterceptorIndex 表示执行的拦截器索引默认等于-1,首先判断是否有拦截器执行目标方法,


或者拦截器索引等于拦截器数组大小减一相等(也就是执行到最后一个拦截器)都会执行目标方法。下面我们debug调试,查看拦截器的执行


首先来到第一个拦截器

拦截器索引等于-1,拦截器数组等于4,通过this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);


获得到第一个拦截器,拦截器索引+1,执行interceptorOrInterceptionAdvice).invoke(this)方法,传入的this为ChlibProxy

进入其中

其中invocation是当前线程共享的MethodInvocation,先从其中获得MethodInvocation,再将ChlibProxy加入到当前线程公享数据中,


调用ChlibProxy的procees()方法,进入mi.proceed()中,又来到我们之前的proceed()方发,初始的拦截器索引+1了

然后又重this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);获得第二个拦截器

之后又会调用((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);来到AspectJAfterThrowingAdvice的invoke()方法中

又是调用mi.proceed()方法,又来到proceed()方法,拦截器索引+1,又获的一个拦截器

AfterReturningAdviceInterceptor这个拦截器还是调用((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)方法,进入其中

又调用mi.proceed()方法,来到proceed(),拦截器索引+1,获得一个拦截器

又调用((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)方法,进入其中

又调用mi.proceed()来到proceed()方法,拦截器索引+1,获得一个拦截器

又调用((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)方法,进入其中

这里就调用了前置通知,之后又调用mi.proceed()来到proceed()方法

此时拦截器索引为4,等于拦截器数组大小4,就调用invokeJoinpoint()方法,执行目标方法并返回,之后就调用后置通知

后置通知调用完毕如果有异常就将异常向上抛,执行异常通知

如果没有异常,就执行返回通知

返回通知执行完毕,程序也就跑完了。拦截器链就是链式或去拦截器,调用拦截器的invoke()方法,


每一个拦截器都等待下一个拦截器执行完毕返回以后,在执行。通过拦截器链的机制,保证通知方法与目标方法的执行顺序。


步骤3,拦截器链调用过程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/905750.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何保证消息队列的消息只能被消费一次

如何保证消息队列的消息只能被消费一次,首先先保证消息不会丢失 首先先生产者到消费者到消费者有哪些场景会消息丢失一、问题场景 场景一、生产者发送到消息队列失败 场景二、消息队列接受到消息磁盘化失败 场景三、消费者接受到消息消费失败 二、场景原因,如何解决 1、场景一…

Day22_java方法

Java方法 方法重载 package com.xiang.method;public class Demo02 {public static void main(String[] args) {int max = max(20, 100, 10);System.out.println(max);}// 比大小public static int max(int num1,int num2){int result = 0;if (num1 == num2){System.out.printl…

文献阅读《Spectral Networks and Deep Locally Connected Networks on Graphs》

参考博客 第一代图卷积网络:图的频域网络与深度局部连接网络 - 知乎 (zhihu.com) 论文解读一代GCN《Spectral Networks and Locally Connected Networks on Graphs》 - 别关注我了,私信我吧 - 博客园 (cnblogs.com) 论文核心 卷积神经网络得益于所处理的数据具有局部平移不变…

【CodeForces训练记录】Codeforces Round 1013 (Div. 3)

训练情况赛后反思 A题题目读半天,发现日期有前导零,div3还是比较基础一点,但是感觉自己还是不够熟练,D题看出来二分但是调了挺久的 A题 判断取多少个数之后才能构成 20250301,我们维护数字的出现次数,直到所有数字的出现次数全部大于等于 20250301 的出现次数时输出位置即…

字符串问题的江湖奇宝:进制哈希

江湖中,剑客以快制胜,而算法竞赛里,字符串哈希(String Hashing)便是那柄出招如电的快剑。 各种字符串问题纷乱复杂,各种字符串算法招式繁复,需苦练内功心法。但字符串哈希算法却只凭一招:将字符串化作数字,以数论为刃,至简之道斩尽来犯之敌。 但此招并非无懈可击。若…

HW-1

1.选项A是正确的,它表示的是极小项m6的正确形式。极小项m6对应的是变量a=0,b=1,c=1,d=0的情况,因此其表达式应为(\overline{a} \cdot b \cdot c \cdot \overline{d}),即选项A。 其他选项的分析:选项B是一个或项,不符合极小项的定义。 选项C缺少变量a和d,不是一个完整的…

为什么nn.Linear 的weight 是 (out_features, in_features)

在PyTorch的nn.Linear中,权重矩阵的形状为(out_features, in_features)。这是因为线性变换的实现方式为:具体来说:当创建nn.Linear(10, 60)时,in_features=10,out_features=60,因此权重的形状是(60, 10)。 输入张量t的形状为(2, 5, 10),与转置后的权重a.weight.T(形状(…

字符串问题的终极法宝:进制哈希

江湖中,剑客以快制胜,而算法竞赛里,字符串哈希(String Hashing)便是那柄出招如电的快剑。 各种字符串问题纷乱复杂,各种字符串算法招式繁复,需苦练内功心法。但字符串哈希算法却只凭一招:将字符串化作数字,以数论为刃,至简之道斩尽来犯之敌。 但此招并非无懈可击。若…

布局机器人,vivo用三十年技术沉淀回答“时代之问”

科技创新给产业界带来最大的影响就是“跨界焦虑”。不敢错过,这是企业面对风口的普遍心态。生怕一波没跟上,就被时代淘汰了。 但不错过,并不等于抓得住。比如元宇宙概念经历资本狂欢,无数科技巨头卷入,退潮时一地鸡毛。再比如在新能源汽车赛道卷起千亿投资风暴时,也有很多…

石油化工厂区防爆入侵报警系统

石油化工厂区防爆入侵报警系统采用AI智能防爆预警摄像头嵌入AI人体识别深度算法,对人体目标特征的检测分析识别预警。系统设备采用AI算法,通过大量真实的场景样本训练后,能够在各种应用场景下及时准确地对场景中发生的人体入侵行为发出告警信息。通过对实时视频图像进行智能…