Spring源码阅读:AOP原理

news2024/11/26 17:32:44

一、概述

以下便是Spring Aop的流程,下面我将一一介绍下面的各个方法。

下面是流程中的主要方法。 

 

 

 

二、测试代码

下面我将写一个例子介绍Spring Aop的流程。

被增强类:

public class MyCalculator {
    public Integer add(Integer i, Integer j) throws NoSuchMethodException {
        Integer result = i+j;
        return result;
    }

    public Integer sub(Integer i, Integer j) throws NoSuchMethodException {
        Integer result = i-j;
        return result;
    }

    public Integer mul(Integer i, Integer j) throws NoSuchMethodException {
        Integer result = i*j;
        return result;
    }

    public Integer div(Integer i, Integer j) throws NoSuchMethodException {
        Integer result = i/j;
        return result;
    }

    public Integer show(Integer i){
        System.out.println("show .....");
        return i;
    }

    @Override
    public String toString() {
        return "super.toString()";
    }
}

增强类:

public class LogUtil {

    @Pointcut("execution(public Integer com.mashibing.service.MyCalculator.*(Integer,Integer))")
    public void myPointCut(){}


    private int start(JoinPoint joinPoint){
        //获取方法签名
        Signature signature = joinPoint.getSignature();
        //获取参数信息
        Object[] args = joinPoint.getArgs();
        System.out.println("log---"+signature.getName()+"方法开始执行:参数是"+Arrays.asList(args));
        return 100;
    }


    public static void logFinally(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        System.out.println("log---"+signature.getName()+"方法执行结束。。。。。over");

    }


}

xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
">
    <bean id="logUtil" class="com.mashibing.aop.xml.util.LogUtil" ></bean>
    <bean id="myCalculator" class="com.mashibing.aop.xml.service.MyCalculator" ></bean>
    <aop:config>
        <aop:aspect ref="logUtil">
            <aop:pointcut id="myPoint" expression="execution( Integer com.mashibing.aop.xml.service.MyCalculator.*  (..))"/>
            <aop:before method="start" pointcut-ref="myPoint"></aop:before>
            <aop:after method="logFinally" pointcut-ref="myPoint"></aop:after>
        </aop:aspect>
    </aop:config>
</beans>

测试类:

    public static void main(String[] args) throws Exception {
        ApplicationContext ac = new ClassPathXmlApplicationContext("aop.xml");
        MyCalculator bean = ac.getBean(MyCalculator.class);
        bean.add(1,1);

    }

三、AOP流程

整个 Spring AOP 源码,其实分为 3 块,我们会结合上面的示例,给大家进行讲解。

 

第一块就是前置处理,我们在创建 MyCalculator Bean 的前置处理中,会遍历程序所有的切面信息,然后将切面信息保存在缓存中

第二块就是后置处理,我们在创建 MyCalculator Bean 的后置处理器中,里面会做两件事情:

  • 获取 MyCalculator 的切面方法:首先会从缓存中拿到所有的切面信息,和 MyCalculator 的所有方法进行匹配,然后找到 MyCalculator 所有需要进行 AOP 的方法。
  • 创建 AOP 代理对象:结合 MyCalculator 需要进行 AOP 的方法,选择 Cglib 或 JDK,创建 AOP 代理对象。

第三块就是执行切面,通过“责任链 + 递归”,去执行切面。

(一)代码入口

finishBeanFactoryInitialization是整个aop执行流程的入口。

 通过preInstantiateSingletons方法进入doGetBean

 进入 doGetBean(),进入创建 Bean 的逻辑。

 

(二)前置处理

主要就是遍历切面,放入缓存。

进入前置处理的入口。

遍历找到该对象。

 

 

 

 里面有我们想要的切面信息。

这里是重点!敲黑板!!!

  1. 我们会先遍历所有的类;
  2. 判断是否切面,只有切面才会进入后面逻辑;
  3. 获取每个 Aspect 的切面列表;
  4. 保存 Aspect 的切面列表到缓存 advisorsCache 中。

 

 

( 后置处理

 

主要就是从缓存拿切面,和 MyCalculator的方法匹配,并创建 AOP 代理对象。

进入 doCreateBean(),走下面逻辑。

这里是重点!敲黑板!!!

  1. 先获取MyCalculator类的所有切面列表;
  2. 创建一个 AOP 的代理对象。

 

 

这里是重点!敲黑板!!!

这里有 2 种创建 AOP 代理对象的方式,我们是选用 Cglib 来创建。

(四) 切面执行

 

通过 “责任链 + 递归”,执行切面和方法。

 

 

下面就是“执行切面”最核心的逻辑,简单说一下设计思路:

  1. 设计思路:采用递归 + 责任链的模式;
  2. 递归:反复执行 CglibMethodInvocation 的 proceed();
  3. 退出递归条件:interceptorsAndDynamicMethodMatchers 数组中的对象,全部执行完毕;
  4. 责任链:示例中的责任链,是个长度为 3 的数组,每次取其中一个数组对象,然后去执行对象的 invoke()。

第一次递归

数组的第一个对象是 ExposeInvocationInterceptor,执行 invoke(),注意入参是 CglibMethodInvocation。

里面啥都没干,继续执行 CglibMethodInvocation 的 process()。

第二次递归:

数组的第二个对象是 MethodAfterAdviceInterceptor,执行 invoke()。

第三次递归:

执行完上面逻辑,就会退出递归,我们看看 invokeJoinpoint() 的执行逻辑,其实就是执行主方法。

 

四、疑惑点

AOP增强器的执行顺序如下图,但是责任链的执行顺序却和下图的执行顺序相反的,那么这是为什么呢?因为责任链的执行虽然是相反的,但是它是递归调用的,因此返回结果的时候顺序又是反过来的,正好和下图相同。

参考文章:

76 张图,剖析 Spring AOP 源码,小白居然也能看懂,大神,请收下我的膝盖! - 知乎

https://www.cnblogs.com/xxkj/p/14094203.html

Spring-aop源码解析 - 简书

https://www.cnblogs.com/V1haoge/p/9560803.html

https://www.cnblogs.com/RunningSnails/p/17013513.html

https://www.cnblogs.com/Acaak/p/16828906.html

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

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

相关文章

逼近GPT-4!BLOOMChat: 开源可商用支持多语言的大语言模型

背景 SambaNova和Together这2家公司于2023.05.19开源了可商用的支持多语言的微调模型BLOOMChat。 SambaNova这家公司专注于为企业和政府提供生成式AI平台&#xff0c;Together专注于用开源的方式打造一站式的foundation model&#xff0c;赋能各个行业。 OpenAI的GPT-4和Goo…

【将maven源改为国内阿里云镜像】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 1. 如何配置Maven镜像&#xff1f; 2. Idea中m…

【Java入门】初识Java

前言 &#x1f4d5;作者简介&#xff1a;热爱跑步的恒川&#xff0c;致力于C/C、Java、Python等多编程语言&#xff0c;热爱跑步&#xff0c;喜爱音乐的一位博主。 &#x1f4d7;本文收录于Java入门篇系列&#xff0c;该专栏主要讲解&#xff1a;什么是java、java的数据类型与变…

MATLAB|004|MATLAB M-Files|MATLAB数据类型

MATLAB M-Files 我们一直强调MATLAB是一个功能强大的编程语言及交互式计算环境&#xff0c;之前学习的内容中&#xff0c;我们学会了在 MATLAB 命令提示符下输入命令&#xff0c;而且我们主要是把MATLAB环境作为一个计算器使用。其实&#xff0c;MATLAB 还允许写入到一个文件中…

5分钟掌握利用pycharm插件BitoAI 实现chatgpt自动编写代码

一、BitoAI 简介 最近出现了一款新型编程助手BitoAI。今天的主要内容就是给大家介绍它&#xff0c;号称 IDE 的“瑞士军刀”&#xff0c;可以提升开发 10 倍的效率。 简言之它的强大之处就是可以通过类似于ChatGPT对话的方式来编写代码&#xff0c;分析代码&#xff0c;生成代…

Flutter控件之Tab选项卡封装

Tab选项卡&#xff0c;这是一个非常常见且权重很高的一个组件&#xff0c;随便打开一个App&#xff0c;比如CSDN&#xff0c;如下图&#xff0c;首页顶部就是一个Tab选项卡&#xff0c;这个功能可以说&#xff0c;几乎每个App都会存在。 在Android中&#xff0c;我们可以使用Ta…

“Shell“iptales防火墙设置

文章目录 一.Linux防火墙基础1.1Linux包过滤防火墙概述1.2四表五链1.3规则链之间的匹配顺序1.4规则链内的匹配顺序1.5总结 二.编写防火墙规则2.1iptables防火墙的配置方法2.2规则的匹配2.3命令使用 一.Linux防火墙基础 1.1Linux包过滤防火墙概述 Linux 系统的防火墙: IP信息包…

惯性导航论文详解:神经惯性定位

来源&#xff1a;投稿 作者&#xff1a;小灰灰 编辑&#xff1a;学姐 论文标题&#xff1a;Neural Inertial Localization 论文链接: https://arxiv.org/pdf/2203.15851v1.pdf 图1.从IMU测量到位置估计。给定惯性传感器数据&#xff08;左&#xff09;&#xff0c;我们的方法…

C#,生信软件实践(04)——DNA数据库EMBL格式文件的解释器之完整源代码

EMBL文件的格式详解请阅读前面的文章&#xff1a; C#&#xff0c;生信软件实践&#xff08;02&#xff09;——DNA数据库EMBL格式详解及转为FASTA格式文件的源代码https://blog.csdn.net/beijinghorn/article/details/130462070 本文的代码用于&#xff1a; &#xff08;1&a…

Linux---文件操作命令(cp、mv、rm)

1. cp命令 cp命令可以用于复制文件\文件夹&#xff0c;cp命令来自英文单词&#xff1a;copy。 语法&#xff1a;cp [选项] 参数1 参数2 参数1&#xff1a;Linux路径&#xff0c;表示被复制的文件或文件夹 参数2&#xff1a;Linux路径&#xff0c;表示要复制去的地方 选…

《Java 核心技术面试》课程笔记(十一)

Java 提供了哪些 IO 方式&#xff1f; 典型回答 Java IO 基于不同的 IO 抽象模型和交互方式&#xff0c;可以分为&#xff1a; BIO&#xff0c;传统的 java.io 包&#xff0c;它基于流模型实现。 提供了我们最熟知的⼀些 IO 功能&#xff0c;比如 File 抽象、输入输出流等。交…

安装编译PostgreSql15.3.0

一、下载源码 方式一 官网手动下载 https://www.postgresql.org/download/. 解压 tar -zxvf postgresql-14.2.tar.gz方式二 git clone git clone https://github.com/postgres/postgres.git解压或下载后计入postgres目录 cd postgres-15.3二、创建目录 用root账户创建 创建…

[iOS开发]<多线程-NSOperation操作队列NSOperationQueue>

前言 寒假期间学习过GCD。今天学习NSOperation。同样都是多线程封装&#xff0c;NSOperation和NSOperationQueue是基于GCD的更高一层的封装&#xff0c;完全的面向对象&#xff0c;相比于GCD复杂的各种API方法&#xff0c;它的优势就是更加的简单实用&#xff0c;代码的可读性…

电力电子课设—数控产生PWM波——使用51单片机输出占空比可调PWM波(按钮控制、数码管显示)控制速成教程

我们学校电气专业开始做电力电子的课设了&#xff0c;小组选了一项制作硬件电路的任务&#xff0c;里面有要求采用数控方式实现DC-DC电压变换的输出电压调节&#xff0c;数控在电路中的体现就是用单片机输出可调占空比的PWM作用于产生PWM波控制IGBT的芯片。考虑到可能有同学没接…

金领冠520解密母乳源代码,助推婴配粉中国式现代化高速发展

又是一年520&#xff0c;又是一个“全国母乳喂养宣传日”。 1990年5月10日&#xff0c;为保护、促进和支持母乳喂养&#xff0c;更好地实行优生优育&#xff0c;原中华人民共和国国家卫生部召开新闻发布会&#xff0c;确立每年5月20日为“全国母乳喂养宣传日”。 那时&#x…

[GXYCTF2019]BabySQli1

拿到题目一看就是sql注入&#xff0c;所以还是老样子账号admin密码随便输入&#xff0c;回显但是密码错误 当用户名随便输入时&#xff0c;回显用户名错误&#xff0c;说明是先检测用户名&#xff0c;再检测密码 应该是存在过滤 通过burp爆破大致找出过滤字符&#xff0c;还有就…

css flex布局

css flex布局 flex是flexible Box的缩写&#xff0c;意为“弹性布局”&#xff0c;任何一个容器都可以指定为flex布局。 当我们为父盒子设为flex布局以后&#xff0c;子元素的float、clear和vertical-align属性将失效 总结flex布局原理&#xff1a; 就是通过给父盒子添加fl…

Java - AQS(一)

Java - AQS&#xff08;一&#xff09; 在Java中&#xff0c;AQS代表AbstractQueuedSynchronizer&#xff08;抽象队列同步器&#xff09;。AQS是Java并发包中用于构建同步器的基础框架。它提供了一种实现同步状态管理、线程等待和通知的机制。 AQS主要通过一个int类型的状态…

轻松玩转开源大语言模型bloom(四)

前言 前几篇都围绕着语言模型的decoding strategy来讲述&#xff0c;今天将进入进阶篇&#xff0c;在解码策略效果有限和提示词修改也无法满意的情况下如何提升模型的效果呢&#xff1f;这时我们需要对大语言模型进行fine-tune&#xff0c;即微调。一般我们用的大语言模型都是…

chatgpt赋能Python-python5个数从小到大排序

Python中的5个数从小到大排序 在Python中&#xff0c;排序是一个常见的操作。我们经常需要对一组数据进行排序&#xff0c;以便更方便地对数据进行分析和处理。在本文中&#xff0c;我们将探讨Python中如何排序5个数&#xff0c;具体来说&#xff0c;是从小到大排序。 介绍 …