Spring源码阅读:AOP原理

一、概述

以下便是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执行流程

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring AOP中,拦截器责任链处理过程是指当目标方法被多个通知匹配到时,Spring通过引入拦截器链来保证每个通知的正常执行。拦截器链是由一系列的拦截器组成的,每个拦截器都负责在目标方法的前后执行特定的逻辑。 在源码中,拦截器责任链的处理过程主要通过MethodInvocation接口来实现。MethodInvocation接口提供了proceed()方法,用于执行拦截器链中下一个拦截器的逻辑。当调用proceed()方法时,会按照拦截器链的顺序依次执行每个拦截器的逻辑,直到达到链的末尾或者某个拦截器决定终止链的执行。 在拦截器责任链处理过程中,每个拦截器可以在目标方法的调用前后执行自定义的逻辑。拦截器可以对方法的参数进行检查、修改方法的返回值,或者在方法执行前后记录日志等操作。通过拦截器责任链的处理,Spring AOP能够实现面向切面编程的功能。 需要注意的是,拦截器链的执行顺序是根据拦截器的配置顺序确定的。在Spring的配置文件中,可以通过配置拦截器的顺序来控制拦截器链的执行顺序。这样可以确保每个拦截器按照预期的顺序执行,从而达到期望的功能效果。 总结起来,Spring AOP源码的拦截器责任链处理过程主要通过MethodInvocation接口实现,它通过调用proceed()方法来依次执行拦截器链中每个拦截器的逻辑。拦截器链的执行顺序可以通过配置文件来控制,从而实现面向切面编程的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Spring AOP源码:拦截器责任链处理过程](https://blog.csdn.net/weixin_45031612/article/details/128806966)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Spring AOP 自动代理源码 DefaultAdvisorAutoProxyCreator](https://download.csdn.net/download/weixin_38530536/14854229)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [【SpringSpring AOP 源码分析-拦截器链的执行过程(四)](https://blog.csdn.net/qq_46514118/article/details/121912507)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小海海不怕困难

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值