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

news2024/9/26 1:20:07

首先分析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.coloradmin.cn/o/1615557.html

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

相关文章

OpenCV与AI深度学习 | OpenCV如何读取仪表中的指针刻度

本文来源公众号“OpenCV与AI深度学习”,仅用于学术分享,侵权删,干货满满。 原文链接:OpenCV如何读取仪表中的指针刻度 最近遇到一个问题,如何读取仪表中的指针指向的刻度。 解决方法有多种,比如&#xff…

67条tips实战案例渗透测试大佬的技巧总结

67条tips实战案例渗透测试大佬的技巧总结。 Tips 1. 手动端口探测 nmap的-sV可以探测出服务版本,但有些情况下必须手动探测去验证 使用Wireshark获取响应包未免大材小用,可通过nc简单判断 eg. 对于8001端口,nc连接上去,随便输…

oracle 执行计划详解

执行计划是指示 Oracle 如何获取和过滤数据、产生最终的结果集,是影响SQL 语句执行性能的关键因素。在深入了解执行计划之前,首先需要知道执行计划是在什么时候产生的,以及如何让 SQL 引擎为语句生成执行划。 先了解 SQL 语句的处理执行过程…

LocalAi,Ollama+AnythingLLM搭建部署本地大模型AI知识库,汉化版本

AnythingLLM 是一个全栈应用程序,您可以使用商业现成的 LLM 或流行的开源 LLM 和 vectorDB 解决方案来构建私有 ChatGPT,无需任何妥协,您可以在本地运行,也可以远程托管并能够智能聊天以及您提供的任何文件。 AnythingLLM 将您的文…

【系统架构师】-案例考点(三)

1、信息系统架构ISA设计 四种架构模型: 1)单机应用 2)客户机/服务器模式:两层、三层C/S、B/S模型、MVC模式等 3)面向服务架构SOA 4)企业数据交换总线:不同企业应用之间通过信息交换的公共频…

思科 Packet Tracer 实验八 DHCP基本配置(以路由为中继)

一、实验目的 了解思科网络设备的配置基本特点及 IOS 命令基本操作方法 了解DHCP的工作原理及基本配置 二、实验过程 1) 实验拓扑如下: 2)由于使用DHCP‘协议动态配置ip,所以除了DHCP服务器和路由器接口外其他的主机,服务器的i…

AB5 点击消除

AB5 点击消除 可以用栈来解决。 当栈为空的时候,直接将字符入栈当栈非空的时候 当前字符与栈顶字符相同 出栈 当前字符与栈顶字符不同 入栈 重复上述2步即可。 栈在输出的时候不能从栈底开始输出,需要先把栈顶元素弹出并保存下来,在进行输…

过滤器Filter和拦截器Interceptor心得

上一篇文章讲了监听器Listener,下面我们来讲一下过滤器和拦截器。 一、过滤器Filter。 首先,servlet容器(比如tomcat)肯定的要有servlet才能发挥它的光彩。在上古jsp时代,我们会写各种servlet通过不同的请求来实现我…

E-MapReduce极客挑战赛季军方案

前一段时间我参加了E-MapReduce极客挑战赛,很幸运的获得了季军。在这把我的比赛攻略给大家分享一下,希望可以抛砖引玉。 赛题分析与理解 赛题背景: 大数据时代,上云已成为越来越多终端客户大数据方案的落地选择,阿里…

解锁EDM设计秘籍:关键要素一览,邮件如何设计?

一个成功的EDM邮件需要包含多个关键元素,从内容、设计到呼唤行动,每个环节都至关重要。今天,我们就来探讨EDM邮件中应包含的关键元素?以及如何设计邮件? 一、EDM必备关键要素 1、吸引眼球的主题行 主题行应该简短明了…

2-Embedding例子:简单NN网络、迁移学习例子(glove语料预训练)

一、简单例子:构造简单NN网络生成Embedding 1、pytorch例子 2、tensorflow例子 # 1导入模块 import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Embedding import numpy as np# 2构建语料库 corpus[[…

【更新】cyのMemo(20240422~)

序言 胡哥首马在淮安325完赛,他的本硕都在淮安度过,七年的跑步生涯画上句号,真的是很圆满。七年,从180斤瘦到120斤,历经种种,胡哥理解的跑步,不是快,而是稳,他在比赛中从…

线性表的顺序存储如何设计实现?

如何存储 顺序及链式实现 计算机中的状态

【Java】变量零基础教程

目录 一、引言 二、基本组成单位 三、变量的基本原理 四、变量的基本使用步骤 五、变量快速入门 六、变量使用的注意事项 一、引言 为什么需要变量? ​​​​​​一个程序就是一个世界。 大家看下图,是我们现实中的一张生活照,图里有树…

汕头联想 ibm x3500 M5服务器上门维修记录

汕头联想服务器现场检修;汕尾IBM服务器故障维修;揭阳戴尔服务器维修;汕头ERP服务器维修;潮阳地区各种服务器故障维修;各类服务器主板齐全; 分享一例从东莞到汕头某染料厂维修ibm system x3500 M5服务器的真…

47.基于SpringBoot + Vue实现的前后端分离-校园外卖服务系统(项目 + 论文)

项目介绍 本站是一个B/S模式系统,采用SpringBoot Vue框架,MYSQL数据库设计开发,充分保证系统的稳定性。系统具有界面清晰、操作简单,功能齐全的特点,使得基于SpringBoot Vue技术的校园外卖服务系统设计与实现管理工作…

分布式技术在文本摘要生成中的应用

摘要 自然语言处理首先要应对的是如何表示文本以供机器处理,随着网络技术的发展和信息的公开,因特网上可供访问的数字文档成爆炸式的增长,文本摘要生成逐渐成为了自然语言处理领域的重要研究课题。本文主要介绍了分布式技术在文本摘要生成中…

Oracle21C 引入HR实例(linux)

1、下载资源 https://github.com/oracle-samples/db-sample-schemas点击code(代码)下载 2、上传Sql文件 解压之后将human_resources里的文件复制到demo\schema\目录(具体目录前面的路径是你安装的路径)下,如下图 3、…

argparse模块(详解)

文章目录 一、argparse模块(1)创建命令行解析对象:parser argparse.ArgumentParser()(2)添加命令行参数和选项:parser.add_argument()(3)解析命令行参数:args parser.p…

就业班 第三阶段(nginx) 2401--4.22 day1 nginx1 http+nginx初识+配置+虚拟主机

一、HTTP 介绍 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。 HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件…