从底层分析并详解SpringAOP底层实现

首先分析AOP的实现

  首先切面(Advisor)由通知(Advice)和切点(Pointcut)组成

  包括前置通知后置通知等等最终都会被转化为实现 MethodInterceptor 接口的环绕通知

  先看一段代码了解一下是aop是怎么运作的

  

首先定义了两个类实现了MethodInterceptor接口,这里的 MethodInvocation 是对原始方法的包装同时也是AOP通知功能的实现方式。

首先这里method,target,args都是原始对象的方法参数用于反射调用。构造参数中传入集合的是刚刚来两个实现MethodInterceptor的类。

当这里的proceed方法被调用时,会有一个初始化为0的参数,作用是记录这里第几个调用的Advisor,当所有的Advisor调完后就会执行真正的原始方法。从而形成了递归调用,效果就是我们看到的环绕通知

这是主程序加效果

接下来我们看一下Spring如何实现的

实现时要使用@EnableAspectJAutoProxy注解,它的作用是通过封装Import注解导入一些其他类,它导入了 AnnotationAwareAspectJAutoProxyCreator 类

由于此类是被保护的所以我采用继承的方法去调用相关方法,并自定义了一个Advisor,同时还通过注解去引入

 

这是主程序

@Aspect注解的解析

首先这是一个Bean后处理器方法

首先把原始工厂和beanName封装在 MetadataAwareAspectInstanceFactory 类中,此类用于保存@Aspect注解标注的类信息,紧接着调用 this.advisorFactory.getAdvisors 方法

此方法根据类获得方法信息以及注解信息封装为 InstantiationModelAwarePointcutAdvisorImpl 这种类型的Advisor。

Advisor由Advice和切点表达式组成

通过 findEligibleAdvisors 方法获取工厂中所有的Advisor,然后根据bean的类型进行匹配做代理

不过这里值得注意的是导入了一个org.springframework.aop.interceptor.ExposeInvocationInterceptor 这个类,这个类是为了把信息存放在ThreadLocal中暴露给整个线程

顺带说一下这里的wrapIfNecessary就是存放在三级缓存的那个bean代理的创建方法

重点在 wrapIfNecessary 方法,这个方法内部会在 getAdvicesAndAdvisorsForBean 方法中

调用 findEligibleAdvisors 方法

然后调用createProxy方法

重点来了

此方法内部创建一个ProxyFactory对象,他会把传入的Advisor通过装饰器模式把他们转化为实现了MethodInterceptor接口的环绕通知

proxyTargetClass 和  exposeProxy 

是@EnableAspectJAutoProxy两个可选项,第一个为false代表默认使用jdk生成动态代理,true的话用Cglib。而exposeProxy为true则代表把生成的代理对象存放在ThreadlocalMap中,这样就可以解决嵌套调用时事务失效的功能。

然后调用getProxy方法生成代理对象

然后我们观察代理对象的代理方法

这里的advised就是ProxyFactory 紧接着调用 getInterceptorsAndDynamicInterceptionAdvice 方法

此方法内部获取所有的Advisor然后进行方法匹配,如果匹配就会把Advice包装为环绕通知

首先获得advice,然后包装

就是这样进行包装,然后通过MethodInvocation获取这些环绕通知,调用invoke这样就可以实现递归嵌套调用,比如前置通知转化为环绕通知后只需要在proceed之前调用就行,就完成了转化

最终调用

就是通过创建 Invocation 然后递归调用

这是官方的proceed实现和我们最开始写的类似

由于上面说了会默认加入一个 ExposeInvocationInterceptor 类用于暴露代理接下来就是证明

这里的invocation就是一个ThreadLocal对象它的作用就是让别的MethodInteceptor也可以使用

就好比通过转化后的 MethodBeforeAdviceInterceptor 就需要用

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

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

相关文章

Unity HDRP Water Surface 水系统 基础教程

Unity HDRP Water Surface 水系统 基础教程 Unity Water SurfaceUnity 项目创建Unity Water Surface:Ocean(海洋)简介Ocean:Transform、GeneralOcean:Simulation(仿真模拟)Ocean:Sim…

C++之STL-String

目录 一、STL简介 1.1 什么是STL 1.2 STL的版本 1.3 STL的六大组件 ​编辑 1.4 STL的重要性 二、String类 2.1 Sting类的简介 2.2 string之构造函数 2.3 string类对象的容量操作 2.3.1 size() 2.3.2 length() 2.3.3 capacity() 2.3.4 empty() 2.3.5 clear() 2.3.6…

【IDEA】在IntelliJ IDEA中导入Eclipse项目:详细指南

IntelliJ IDEA和Eclipse是两款常用的集成开发环境(IDE),在软件开发中经常会遇到需要在它们之间迁移项目的情况。本文将重点介绍如何在IntelliJ IDEA中导入Eclipse项目,以帮助开发者顺利地迁移他们的项目,并在IntelliJ …

echarts 堆叠柱状图 顶部添加合计

堆叠有3个,后面加了一个对象显示顶部的数据, 其实主要的代码还是在series 的第四项,需要注意的是 series的第四项中的data需要为 data: [0, 0, 0] 顶部的统计才能显示出来 增加的代码如下 {name: 综合,type: bar,stack: total,label: {sh…

【Java框架】SpringMVC(三)——异常处理,拦截器,文件上传,SSM整合

目录 异常处理解释局部异常处理全局异常 拦截器拦截器介绍作用:拦截器和过滤器之间的区别拦截器执行流程代码实现补充 文件上传依赖配置MultipartResolver编写文件上传表单页APIMultipartFileFile.separator必须对上传文件进行重命名代码示例 SpringMVC文件上传流程多文件上传 …

AWS制作WordPress在国内外的利弊?

AWS作为全球领先的云计算服务供应商,为WordPress提供了强大且灵活的托管环境,使用AWS来搭建和运行WordPress无疑是个不错的选择。即便如此使用AWS制作还是会有些许利弊,九河云作为AWS的合作伙伴来为读者们仔细探讨AWS在WordPress的利弊。 利&…

学python的第十九天

网络通信和访问数据库 1.1 基本的网络知识 TCP/IP IP是低级的路由协议,它将数据拆分在许多小的数据包中,并通过网络将他们发送到某一特定地址,但无法保证所有包都抵达目的地,也不能保证包按顺序抵达 TCP(传输控制协议…

深度学习系列65:数字人openHeygen详解

1. 主流程分析 从inference.py函数进入,主要流程包括: 1) 使用cv2获取视频中所有帧的列表,如下: 2)定义Croper。核心代码为69行:full_frames_RGB, crop, quad croper.crop(full_frames_RGB)。…

Android MVVM架构 + Retrofit完成网络请求

关于Retrofit,这个应该不是一个很新颖的东西了,简单过一下吧 1.由Square公司开发,基于Type-safe的REST客户端。 2.使用注解来定义API接口,使得HTTP请求变得简洁且易于维护。 3.支持同步和异步请求,可与RxJava、Corouti…

【安卓13】解决带GMS编译报super分区空间不足错误

1、错误信息 2、解决方案 不同供应商修改分区大小的文件路径不一样,但是万变不离其宗,根据报错信息全局搜索关键词BOARD_SUPER_PARTITION_SIZE 这里以RK供应商和AML供应商修改为例: (1)RK改法: 根目录下…

全光谱灯对人体的危害?谨记全光谱灯选购要避开的四大套路

全光谱灯对人体的危害有多大?近年来网上关于护眼台灯对视力有害的言论有很多,引发了很多人空前的关注,事实上这未必是一件坏事,因为随着护眼台灯的热度持续上涨,市面上浑水摸鱼的行为增多了不少,有着不少劣…

STM32H7使用FileX库BUG,SD卡挂载失败

问题描述: 使用STM32H7ThreadXFileX,之前使用swissbit牌的存储卡可正常使用,最近项目用了金士顿的存储卡,发现无法挂载文件系统。 原因分析: 调试过程发现,关闭D-Cache可以挂载使用exfat文件系统。 File…

一文看够,植物线粒体基因组分析套路

线粒体堪称生命活动的“能量供给站”,植物线粒体是线粒体基因组研究中难度最高的,其基因组大小差异较大,100kb-10Mb,大部分由非编码DNA序列组成,且有许多同源序列,占基因组总长的2%-60%,基因间区…

制作github.io学术个人主页

制作如图的学术个人主页。About me - Xianwen Ling’s Blog 学术个人主页是一个学者展示个人学术成果和研究方向的重要工具。个人主页可以集中展示学者的研究论文、出版物、演讲和发布的项目等学术成果,这样其他人可以更方便地了解和评估学者的研究贡献。个人主页可…

Maven 安装及配置教程(Windows)【安装】

文章目录 一、 下载1. 官网下载2. 其它渠道 二、 安装三、 配置四、 验证五、 本地仓储配置六、 配置镜像七、 配置JDK八、完整配置九、常用命令十、IDEA 中配置 Maven1. 配置当前项目2. 配置新建 / 新打开 项目 软件 / 环境安装及配置目录 一、 下载 1. 官网下载 安装地址&a…

书生·浦语大模型第二期实战营第七节-OpenCompass 大模型评测实战 笔记和作业

来源: 视频教程:https://www.bilibili.com/video/BV1Pm41127jU/?spm_id_from333.788&vd_sourcef4a51f7f5a63e756f73ad0dff318c1a3 文字教程:https://github.com/InternLM/Tutorial/blob/camp2/opencompass/readme.md 作业来源&#x…

【Hadoop】- MapReduce YARN 初体验[9]

目录 提交MapReduce程序至YARN运行 1、提交wordcount示例程序 1.1、先准备words.txt文件上传到hdfs,文件内容如下: 1.2、在hdfs中创建两个文件夹,分别为/input、/output 1.3、将创建好的words.txt文件上传到hdfs中/input 1.4、提交MapR…

HotSpot JVM 中的应用程序/动态类数据共享

0.前言 本文的目的是详细讨论 HotSpot JVM 自 JDK 1.5 以来提供的一项功能,该功能可以减少启动时间,但如果在多个 JVM 之间共享相同的类数据共享 (CDS) 存档,则还可以减少内存占用。 1.类数据共享 (CDS) CDS 的想法是使用特定格式将预处理…

状态模式和策略模式对比

状态模式和策略模式都是行为型设计模式,它们的主要目标都是将变化的行为封装起来,使得程序更加灵活和可维护。之所以将状态模式和策略模式进行比较,主要是因为两个设计模式的类图相似度较高。但是,从状态模式和策略模式的应用场景…

Pulsar Meetup 深圳 2024 会务介绍

“ Hi,各位热爱 Pulsar 的小伙伴们,Pulsar Meetup 深圳 2024 报名倒计时啦,快来报名。这里汇集了腾讯、华为和谙流科技等大量 Pulsar 大咖,干货多多,礼品多多,不容错过啊。 ” 活动介绍 由 AscentStream 谙…