1.基于注解,首先我们是通过@EnableAspectJAutoProxy()这个注解开起AOP功能,这个注解会导入AspectJAutoProxyRegistrar组件从而将AnnotationAwareAspectJAutoProxyCreator注册到bean定义中。

2.如果容器有对应名字的bean定义,判断下是不是这个class,如果不是就改成AnnotationAwareAspectJAutoProxyCreator,如果没有就直接注册进去,注册bean定义名字叫org.springframework.aop.config.internalAutoProxyCreator。

3.AnnotationAwareAspectJAutoProxyCreator看来这个类是比较重要的了,我们看一下它的继承关系图,可以看到这个类扩展了那些接口,可以看到他是BeanPostProcessor的实现类

4.现在就直接来看之前在bean的实例化过程中第五点提到的org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation这个方法中是寻找切面的过程。这个方法中其实就是去调用我们相应处理器的before和after方法

在applyBeanPostProcessorsBeforeInstantiation方法中我们看到其实会去调用InstantiationAwareBeanPostProcessor这个接口的postProcessBeforeInstantiation这个方法。从我们上面类图中可以看到。我们通过@EnableAspectJAutoProxy注解注册进去的AnnotationAwareAspectJAutoProxyCreator这个正是InstantiationAwareBeanPostProcessor这个的实现类,所以在这里必然会去调用AnnotationAwareAspectJAutoProxyCreator这个实现,但是这里使用了模板方法的设计模式,实际上的方法实现在其父类AbstractAutoProxyCreator这个中的方法。

5.在AbstractAutoProxyCreator类的postProcessBeforeInstantiation方法中会去判断当前创建的类是否是基础类,是否跳过设置,正是shouldSkip这个方法将切面找出来。

6.shouldSkip中会先调用父类的findCandidateAdvisors找事务切面,再调用自己的builder找其他的切面。

7.BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans中会获取到所的bean,循环判断是否是切面类,也就是是否标注了@Aspect注解的,再获取切面类中的增强器,也就是@After,@Before,@AfterReturning,@AfterThrowing,@Around这几个。找到了之后再加入到缓存中。

8.后面的类再进来就直接缓存里面拿出来就行了,不需要再去寻找切面了

9.接下来就是在在bean创建好之后会通过bean的后置处理器创建代理对象返回,并且在代理对象中织入我们的增强器。

10.现在来看AbstractAutoProxyCreator#postProcessAfterInitialization这个方法中的一些逻辑,从缓存中拿到我们之前的找到的增强器信息,并且找到匹配当前类的增强器。

11.找到之后又有一步排序的操作,这个就决定了我们增强器的执行顺序。找到了增强器说明需要生成代理,没有增强器就不需要代理。

12.如果需要创代理对象,则判断我们代理分方式@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true),第一个参数是是否暴露我们代理对象,如果暴露了可以当前原型类中通过AopContext.currentProxy(),获取到代理对象。如下图两种调用方式:一种会被切,一种不会

第二个参数是是否强制只用cglib代理。

判断是何种代理

13.可以看到返回的代理对象里面是有我们的增强器信息的。

至此切面寻找,代理对象创建,增强器织入都完成了,接下来就是我们执行目标方法的时候,这些增强器是如何执行的。

14.代理对象调用方法的时候会将增强器转换成拦截器链,就是根据上说到的排序顺序。

如下图:

15.然后创建一个反射方法的执行器执行proceed()方法 进行一个递归的调用,这里的调用有点绕,初始下标-1,然后通过前++的方式从拦截器链中获取出来执行,当最后都取完了的时候才执行目标方法,通过断点调试会发现调用顺序如下图:

因为是递归的调用所以最先执行结束却是54321的顺序,这就是为什么@Before是在方法执行之前执行,可以看到@AfterThrowing是在try-catch中执行的增强器方法。@After是在一个try-finally中执行的,所以这个始终会被执行。

这就是整个Spirng整个AOP的流程。

Spring aop(1)--- 寻找切面和代理对象执行流程源码分析的更多相关文章

  1. Spring Boot的自动配置原理及启动流程源码分析

    概述 Spring Boot 应用目前应该是 Java 中用得最多的框架了吧.其中 Spring Boot 最具特点之一就是自动配置,基于Spring Boot 的自动配置,我们可以很快集成某个模块, ...

  2. Spring Cloud学习 之 Spring Cloud Ribbon(执行流程源码分析)

    Spring Boot版本:2.1.4.RELEASE Spring Cloud版本:Greenwich.SR1 文章目录 分析: 总结: 分析: ​ 在上篇文章中,我们着重分析了RestTempla ...

  3. Spring -- aop(面向切面编程),前置&后置&环绕&抛异常通知,引入通知,自动代理

    1.概要 aop:面向方面编程.不改变源代码,还为类增加新的功能.(代理) 切面:实现的交叉功能. 通知:切面的实际实现(通知要做什么,怎么做). 连接点:应用程序执行过程期间,可以插入切面的地点. ...

  4. spring AOP AspectJ 定义切面实现拦截

    总结记录一下AOP常用的应用场景及使用方式,如有错误,请留言. 1.  讲AOP之前,先来总结web项目的几种拦截方式    A:  过滤器 使用过滤器可以过滤URL请求,以及请求和响应的信息,但是过 ...

  5. Spring AOP系列(一)— 代理模式

    Spring AOP系列(一)- 代理模式 AOP(Aspect Oriented Programming)并没有创造或使用新的技术,其底层就是基于代理模式实现.因此我们先来学习一下代理模式. 基本概 ...

  6. Spring加载流程源码分析03【refresh】

      前面两篇文章分析了super(this)和setConfigLocations(configLocations)的源代码,本文来分析下refresh的源码, Spring加载流程源码分析01[su ...

  7. 转:Spring与Mybatis整合的MapperScannerConfigurer处理过程源码分析

    原文地址:Spring与Mybatis整合的MapperScannerConfigurer处理过程源码分析 前言 本文将分析mybatis与spring整合的MapperScannerConfigur ...

  8. Java的三种代理模式&完整源码分析

    Java的三种代理模式&完整源码分析 参考资料: 博客园-Java的三种代理模式 简书-JDK动态代理-超详细源码分析 [博客园-WeakCache缓存的实现机制](https://www.c ...

  9. spring boot 加载web容器tomcat流程源码分析

    spring boot 加载web容器tomcat流程源码分析 我本地的springboot版本是2.5.1,后面的分析都是基于这个版本 <parent> <groupId>o ...

随机推荐

  1. linux 下c 链接so 库

    gcc -shared -fPIC -o libname.so  *.c  //生成so库 gcc main.c -om  -Lpath -lname //链接测试so 库 但是生成可执行程序执行时报 ...

  2. [HNOI2006]最短母串问题(AC自动机+状态压缩+bfs)

    快要THUSC了,来水几道模板题吧. 这题其实是AC自动机模板.看到长度最短,首先就想到AC自动机.那么就直接暴力法来吧,把每个串建立在AC自动机上,建立fail指针,然后由于n<=12,可以把 ...

  3. spi设备描述过程

    一.spi通信 中控制器驱动及spi设备.spi设备驱动的关系入下图: 控制器驱动以及设备全志已经完成,在/driver/spi/spi--sunxi.c  中,打开源码文件可以看到spi控制器属于平 ...

  4. 深入理解Java接口

    一.接口的特点 接口中可以有变量和方法,接口中的变量会隐式的指定为public static final变量(并且只能是public static final变量),而方法会被隐式的指定为public ...

  5. linux配置和查看环境变量

    环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数,比如临时文件夹位置和系统文件夹位置等等. 一.Linux的变量种类 按变量的生存周期来划分,Linux变量可分为两类: 1.永久的:需要 ...

  6. 网页元素检测工具:Spy_for_InternetExplorer下载地址

    本工具用于实时查看IE浏览器中打开的网页中元素的信息.支持iframe.frame框架. 下载地址: Spy_for_InternetExplorer.rar

  7. 允许外部访问Windows本机的指定端口

    背景:目前公司有一台公网Windows服务器,有公网IP和内网IP,防火墙已开启 需求:9999端口需要对外开放 方案:在防火墙的入站规则里添加一条规则,使外部能够访问9999端口 问题:添加好规则后 ...

  8. Computing Essentials_第一章习题

  9. Google DevTools Explanation

    Evaluating network performance The Network panel records information about each network operation in ...

  10. 虚拟机apache启动

    /usr/local/apache2/bin/apachectl restart 重启 当启动也行 尝试过进入目录运行,比较奇怪,www目录竟然不一致,直接使用 server httpd start ...