Spring IoC、AOP 原理小总结

  • 前言
  • 版本约定
  • 正文
    • Spring BeanFactory 容器初始化过程
    • IoC 的过程
      • bean 完整的创建流程如下
    • AOP 的过程
      • AnnotationAwareAspectJAutoProxyCreator
      • AOP 代理的创建过程
      • Advice 执行的过程
  • 小结
  • SpringIoC源码视频讲解:

前言

Spring 框架提供了两大功能: IoC 和 AOP,它能对 bean 的全生命周期进行管理。

其它框架如果能被纳入到 Spring 容器的管理的话,那么这个框架的 bean 也就具备了 IoC 和 AOP 的能力。
所以,其他框架与 Spring 整合的过程,可以理解为"将其他框架纳入到 Spring 容器中来管理"的过程。

前面的文章已经透过源码分析过了 IoC 和 AOP,这里,再对 Spring 框架来进行一个小小的总结。

版本约定

Spring 5.3.9 (通过 SpringBoot 2.5.3 间接引入的依赖)

正文

Spring 框架为了实现 IoC 的功能,引入了 Spring BeanFactory 容器的概念(即:Spring IoC 容器)。

Spring 框架要处理的主要功能可以概括为 3 块:

  1. BeanFactory 容器的初始化
  2. IoC 的过程
    2.1 bean 实例的创建
    2.2 bean 依赖的注入
  3. AOP 的过程
    3.1 找到所有与 bean 匹配的 Advisor
    3.2 通过 Advisor 创建 AOP 代理类

下面我们通过流程图的方式来展现一下 Spring 的处理过程,记录一下关键的处理类 和 处理流程,方便更好的理解 Spring,也方便快速的定位到关键的处理类。

Spring BeanFactory 容器初始化过程

我们讲 Spring 容器,通常都是说的 Spring 的 bean 容器,也就是 BeanFactory(org.springframework.beans.factory.BeanFactory)。

下面几种叫法说的是同一个东西:
Spring 容器
Spring bean 容器
Spring IoC 容器
Spring BeanFactory 容器

BeanFactory 的初始化主要是通过 AbstractApplicationContext#refresh() 来完成的,主要过程如下:

AbstractApplicationContext#refresh()

IoC 的过程

IoC 是"控制反转" 和 “依赖注入” 功能的总称。
BeanFactory 初始化流程中 finishBeanFactoryInitialization() 会触发所有非 lazy bean 的加载。也就是会进行 bean 实例的创建 和 依赖关系的注入。

bean 的创建过程过程主要可分为三步:

  1. 创建 bean 的实例: createBeanInstance
  2. 填充 bean 的依赖: populateBean
  3. 初始化 bean: initializeBean

bean 完整的创建流程如下

其中,Aware 接口设置值有两个地方会触发,触发的先后顺序不太一样:

  • AbstractAutowireCapableBeanFactory#invokeAwareMethods()
    处理 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
    是在 initializeBean() 时最先触发的,属于 bean 创建的第三步。

  • ApplicationContextAwareProcessor#invokeAwareInterfaces()
    处理 EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationStartupAware、ApplicationContextAware
    是 BeanPostProcessor#postProcessBeforeInitialization() 触发的,属于 bean 创建的第三步

所以,Aware 接口设置值有两个地方会触发,但是都是在 bean 创建的第三步 initializeBean 时调用的。

AOP 的过程

Spring 中通过 Pointcut 来将 bean 中的 join point 与 Advisor 进行匹配。
AOP 动态代理类的创建是在 bean 的创建过程的第三步 initializeBean 时,通过 AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInitialization() 来创建的。

AnnotationAwareAspectJAutoProxyCreator

在 Spring 中,AOP 代理类是放在 BeanPostProcessor 这个扩展点中来处理的。具体是通过 AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInitialization 来实现的。

AnnotationAwareAspectJAutoProxyCreator 的类图如下:
创建 AOP 代理类的主要功能是由 AbstractAutoProxyCreator 来完成的。

AbstractAutoProxyCreator:
它是 BeanPostProcessor 的实现类,它会获取到所有与 bean 相匹配的 advisor,用于创建 AOP 代理类。

AnnotationAwareAspectJAutoProxyCreator:
它继承了 AbstractAutoProxyCreator,它能从 application context 中获取所有 AspectJ 注解形式的 advisor 用于创建 AOP 代理类。

在 Spring 中,AOP 代理类的创建主要是由 AbstractAutoProxyCreator 来完成的,具体的实现类是 AnnotationAwareAspectJAutoProxyCreator。
其实,在 Spring 中还有一个类 AbstractAdvisingBeanPostProcessor 也用于生成 AOP 代理类,只不过它是指定 advisor 的方式来生成 AOP 代理类的。

@Transactional 是通过 AbstractAdvisorAutoProxyCreator 来实现的。
@Async 是通过 AbstractAdvisingBeanPostProcessor 来实现的。
具体可以查看:
【Spring源码三千问】Spring AOP 中 AbstractAdvisorAutoProxyCreator、AbstractAdvisingBeanPostProcessor的区别
【老王读Spring AOP-5】@Transactional产生AOP代理的原理
【老王读Spring AOP-6】@Async产生AOP代理的原理

AOP 代理的创建过程

在创建 AOP 代理类之前,需要提前将所有的 Advisor 都找出来,然后,在创建代理类时,再通过 AspectJ 表达式去匹配与当前 bean 相关的 Advisor。

proxyTargetClass 标识决定了到底使用 cglib 还是 JDK proxy。
关于 proxyTargetClass 的知识请戳:【Spring源码三千问】Spring动态代理:什么时候使用的 cglib,什么时候使用的是 jdk proxy?

Advice 执行的过程

Spring AOP 代理类的实现有两种:JDK proxy 或者是 CGLIB proxy。
执行 AOP 代理类的 Advice 时,都会经过两步:

  1. 获取 method 对应的 advice chain
  2. 执行 advice chain 及 join point(目标方法)

小结

Spring 框架提供了 IoC 和 AOP 两大功能,它能对 bean 的全生命周期进行管理。
Spring 框架的主要功能可以概括为 3 块:

  1. BeanFactory 容器的初始化
  2. IoC 的过程
    2.1 bean 实例的创建
    2.2 bean 依赖的注入
  3. AOP 的过程
    3.1 找到所有与 bean 匹配的 Advisor
    3.2 通过 Advisor 创建 AOP 代理类

掌握了 IoC 和 AOP 的原理之后,对 Spring 的二次封装扩展 和 与其他框架整合大有裨益。
当项目启动报错时,也能结合源码的知识快速定位出原因。


SpringIoC源码视频讲解:

课程 地址
SpringIoC源码解读由浅入深 https://edu.51cto.com/sd/68e86

如果本文对你有所帮助,欢迎点赞收藏!

源码测试工程下载:
老王读Spring IoC源码分析&测试代码下载
老王读Spring AOP源码分析&测试代码下载

公众号后台回复:下载IoC 或者 下载AOP 可以免费下载源码测试工程…

文章,请关注公众号: 老王学源码


系列博文:
【老王读Spring AOP-0】SpringAop引入&&AOP概念、术语介绍
【老王读Spring AOP-1】Pointcut如何匹配到 join point
【老王读Spring AOP-2】如何为 Pointcut 匹配的类生成动态代理类
【老王读Spring AOP-3】Spring AOP 执行 Pointcut 对应的 Advice 的过程
【老王读Spring AOP-4】Spring AOP 与Spring IoC 结合的过程 && ProxyFactory 解析
【老王读Spring AOP-5】@Transactional产生AOP代理的原理
【老王读Spring AOP-6】@Async产生AOP代理的原理
【Spring 源码阅读】Spring IoC、AOP 原理小总结

相关阅读:
【Spring源码三千问】Spring动态代理:什么时候使用的 cglib,什么时候使用的是 jdk proxy?
【Spring源码三千问】Advice、Advisor、Advised都是什么接口?
【Spring源码三千问】没有AspectJ,Spring中如何使用SpringAOP、@Transactional?
【Spring源码三千问】Spring AOP 中 AbstractAdvisorAutoProxyCreator、AbstractAdvisingBeanPostProcessor的区别
【Spring 源码三千问】同样是AOP代理bean,为什么@Async标记的bean循环依赖时会报错?

【Spring 源码阅读】Spring IoC、AOP 原理小总结相关推荐

  1. 转 Spring源码剖析——核心IOC容器原理

    Spring源码剖析--核心IOC容器原理 2016年08月05日 15:06:16 阅读数:8312 标签: spring 源码 ioc 编程 bean 更多 个人分类: Java https:// ...

  2. Spring源码阅读一——IOC

    spring模块化设计: 接下来我会从最核心的模块开始阅读:Core Container 对应源码 Spring 3.2.X: http://docs.spring.io/spring/docs/3. ...

  3. Spring源码阅读(一)——整体结构

    Spring 总共大约有20个模块,由1300多个不同的文件构成. Spring源码阅读可以分为三个路线:IOC,AOP,外部组件. 个人主页:tuzhenyu's page 原文地址:Spring源 ...

  4. Spring源码阅读之bean对象的创建过程

    Spring源码阅读之bean对象的创建过程 ​ Spring是通过IOC容器来管理对象的,该容器不仅仅只是帮我们创建了对象那么简单,它负责了对象的整个生命周期-创建.装配.销毁.这种方式成为控制反转 ...

  5. spring源码阅读(3)-- 容器启动之BeanFactoryPostProcessor

    接着上文<spring源码阅读(2)-- 容器启动之加载BeanDefinition>,当spring加载完所有BeanDefinition时,并不会马上去创建bean,而是先配置bean ...

  6. 【spring源码分析】IOC容器初始化(二)

    前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...

  7. spring源码深度解析— IOC 之 默认标签解析(下)

    默认标签中的自定义标签解析 注册解析的BeanDefinition 通过beanName注册BeanDefinition 通过别名注册BeanDefinition alias标签的解析 import标 ...

  8. spring源码深度解析---创建AOP代理之获取增强器

    spring源码深度解析-创建AOP代理之获取增强器 在上一篇的博文中我们讲解了通过自定义配置完成了对AnnotationAwareAspectJAutoProxyCreator类型的自动注册,那么这 ...

  9. Spring源码系列- Spring Beans - 核心类的基本介绍

    Spring源码系列- Spring Beans - 核心类的基本介绍 读过上一篇文章的读者应该都能对Spring的体系结构有一个大致的了解,在结尾处,我也说过会从spring-beans包开始分析, ...

最新文章

  1. 洛谷 1195 口袋的天空
  2. python的烦恼_还在为每天忘记签到而烦恼吗?python来帮你搞定!
  3. error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug...
  4. 智能仪表参数设定c语言,智能仪表控制系统:.doc
  5. 在路上(on the road)
  6. java支付管理有源码_java支付宝支付案例源码
  7. 847方波放大电路_分析运放7大经典电路,有图有真相,详解每个电路原理!
  8. 状态机设计的一般步骤_浅谈状态机
  9. 具体的压栈指令,例子
  10. MarkdownPad2添加目录(输出为HTML时可用)
  11. JavaSE----变量、String、运算符、流程控制
  12. 【绘图】matlab 绘制窗口分布
  13. SmartBear继SoapUI Pro 5 2之后推出新版本改名SoapUI NG Pro
  14. Windows下python安装pymyssql报错
  15. Java| Javadoc生成Java帮助文档
  16. arduino(16):使用ESP32的SPI接入PS2手柄,修改LIB解决ESP32兼容问题,setup进行while循环验证,直到加载成功,修改别人代码上传到github上。
  17. html 怎么做图标在圆圈上旋转,纯CSS3图标旋转效果
  18. 记一个印象深刻的项目
  19. Java数组初始化, 冒泡排序, 查找
  20. Inno Setup选择语言并写入配置文件、翻译提示信息

热门文章

  1. 如何在现实场景中随心放置AR虚拟对象?
  2. 【疑难杂症】allennlp安装报错:Installing build dependencies ... error
  3. excel导入mysql并批量查询_Excel导入MySql数据库批量操作
  4. python获取网页数据后写入mysql_HTTP协议与使用Python获取数据并写入MySQL
  5. 全国大学生网络安全精英赛复赛笔记
  6. 德系车,美系车,日系车都有什么品牌
  7. host文件的详解与修改方式
  8. 【教你一招】查看浏览器的Cookie
  9. Nginx集群部署方案
  10. java语言实现的时间片轮转调度算法和动态优先级调度算法