Spring之AOP源码解析(上)

Aop相关注解

  • @EnableTransactionManagement
  • @EnableAspectJAutoProxy
  • @EnableAsync
  • ...

从注解切入来看看这些注解都干了什么

@Import注解作用简述

注入的类一般继承ImportSelector或者ImportBeanDefinitionRegistrar接口

  • 继承ImportSelector接口:selectImports方法返回的类名会被解析成bean
  • 继承ImportBeanDefinitionRegistrar接口:会在解析阶段执行registerBeanDefinitions方法

Spring解析流程可以看我之前写的博文 《Spring之ConfigurationClassPostProcessor解析流程》重点讲解了@Import等注解是如何解析的

@EnableAsync注解

@EnableAsync注解作用
  • 注入一个类型为AsyncAnnotationBeanPostProcessor的BeanPostProcessor

@EnableTransactionManagement注解

@EnableTransactionManagement注解作用
  • 注入一个类型为InfrastructureAdvisorAutoProxyCreator的BeanPostProcessor
  • 注入事务相关的bean

@EnableAspectJAutoProxy

@EnableAspectJAutoProxy注解作用
  • 注入一个类型为AnnotationAwareAspectJAutoProxyCreator的bpp

@EnableTransactionManagement和@EnableAspectJAutoProxy注解的渊源

从方法的角度

两个类都是通过AopConfigUtils.registerXXX方法注入一个bpp到spring中

注意点:AopConfigUtils的register方法存在三个优先级,如果spring调用了多次register方法,spring会保留优先级最高的bpp(beanName为org.springframework.aop.config.internalAutoProxyCreator)。比如Spring中同时存在@EnableTransactionManagement和@EnableAspectJAutoProxy注解,但因为@EnableAspectJAutoProxy注解注入的bpp的优先级高于@EnableTransactionManagement注解注入的bpp,所以spring只有一个类型为AnnotationAwareAspectJAutoProxyCreator的bean,而不存在类型为InfrastructureAdvisorAutoProxyCreator的bean

相关源码AopConfigUtils#registerOrEscalateApcAsRequired

从类的的角度

两个bpp都继承AbstractAutoProxyCreator,然而Spring动态代理相关的逻辑都是在这个类中处理的,所有我们可以认为@EnableTransactionManagement和@EnableAspectJAutoProxy注解实现动态代理的逻辑是一样的。

注解实现动态代理的时机

@EnableAsync注解

我们从前文中了解到@EnableAsync注解会注入一个类型为AsyncAnnotationBeanPostProcessor的bpp,我们来查看源码

我们通过类的继承关系,关注其祖父类(AbstractAdvisingBeanPostProcessor)的postProcessAfterInitialization方法

@EnableTransactionManagement和@EnableAspectJAutoProxy注解

通过上文的分析,我们主要查看AbstractAutoProxyCreator的postProcessAfterInitialization方法

通过源码,我们得出以下几个结论

  • 几个注解注入的bpp都是通过postProcessAfterInitialization方法进行动态代理
  • Spring是通过ProxyFactory这个类完成动态代理的

Spring是如何解决多个bpp对bean进行处理的顺序问题

我们回过头查看@EnableAsync注解注入的bpp的postProcessAfterInitialization方法

从码义上来说,@EnableAsync注解进行AOP动态代理优先级是比较低的,那Spring是怎么处理,让优先级比较低的bpp稍后执行呢?

我们查看源码PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors

Spring会对所有的bpp进行排序,然后按顺序加入到列表中,优先级较高的优先加入,优先处理

这里的比较器使用的是AnnotationAwareOrderComparator,这个比较器大致分成以下步骤

  1. bpp是否继承PriorityOrdered接口,如果都继承PriorityOrdered接口,比较getOrder方法返回的值,值越小,优先级越高
  2. bpp是否继承Ordered接口,如果都继承Ordered接口,比较getOrder方法返回的值,值越小,优先级越高
  3. bpp所属class上是否存在@Order注解,如果存在,比较@Order注解设置的值,值越小,优先级越高
  4. 其他

这里需要注意的是,如果一个bpp继承PriorityOrdered接口,getOrder方法返回的值为100,另外一个bpp继承Ordered接口,getOrder方法返回的值为1,按照第一优先级规则,还是继承PriorityOrdered接口的bpp优先级高

我们查看三个注解相关源码

@EnableAsync注解order默认值是Ordered.LOWEST_PRECEDENCE(Integer.MAX_VALUE)

@EnableTransactionManagement注解order默认值是Ordered.LOWEST_PRECEDENCE(Integer.MAX_VALUE)

@EnableAspectJAutoProxy注解未开启设置

默认的情况下,@EnableAsync和@EnableTransactionManagement注解注入的bpp都继承Ordered接口,并且getOrder方法返回的值都是Ordered.LOWEST_PRECEDENCE(Integer.MAX_VALUE),默认情况下优先级一致,但是@EnableTransactionManagement注解注入bpp的时候,对order值进行了手动设置,保证了如果同时存在@EnableAsync和@EnableTransactionManagement注解的情况下,@EnableTransactionManagement注解注入的bpp进行AOP动态代理,@EnableAsync注解注入的bpp进行增强。如果只存在@EnableAsync注解,则相关bpp进行AOP动态代理

相关源码AopConfigUtils#registerOrEscalateApcAsRequired

这里需要说明一下,虽然@EnableAspectJAutoProxy注解不能指定order值,但是有默认值,默认值也是Ordered.LOWEST_PRECEDENCE(Integer.MAX_VALUE),@EnableTransactionManagement和@EnableAspectJAutoProxy注解从一定程度上来说,这些可以指定的参数是互补的,因为它们进行AOP动态代理的是操作是通过共同父类AbstractAutoProxyCreator完成的

总结

  • @EnableTransactionManagement,@EnableAspectJAutoProxy,@EnableAsync注解都有可能产生AOP动态代理
  • @EnableTransactionManagement,@EnableAspectJAutoProxy注解注入的bpp,都是依靠AbstractAutoProxyCreator这个类完成动态代理的。如果它们同时存在,Spring中只会存在一个优先级更高的bpp。这两个注解指定的参数是互补的,对于特定需求,可以进行扩展
  • 几个注解注入的bpp,都是Spring执行到postProcessAfterInitialization方法阶段,完成AOP动态代理
  • Spring通过registerOrEscalateApcAsRequired方法手动修改了@EnableTransactionManagement,@EnableAspectJAutoProxy注入的bpp的order值,所以执行顺序优先于@EnableAsync注入的bpp
  • 几个注解都是通过ProxyFactory这个类,以策略模式完成AOP动态代理(我们下一篇文章将重点讲解这个类)

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

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

相关文章

pandas/geopandas 笔记:判断地点在不在路网上 不在路网的点和路网的距离

0 导入库 import osimport pandas as pd pd.set_option(display.max_rows,5)import osmnx as oximport geopandas as gpd from shapely.geometry import Point 1 读取数据 假设我们有 如下的数据: 1.1 新加坡室外基站位置数据 cell_stationpd.read_csv(outdoor…

TSINGSEE青犀AI智能分析网关V4初始配置与算法相关配置介绍

TSINGSEE青犀AI智能分析网关V4内置了近40种AI算法模型,支持对接入的视频图像进行人、车、物、行为等实时检测分析,上报识别结果,并能进行语音告警播放。硬件管理平台支持RTSP、GB28181协议、以及厂家私有协议接入,可兼容市面上常见…

linux下ffmpeg调用GPU硬件解码(VDPAU/VAAPI)保存文件

本文讲解在linux下面,如何通过ffmpeg调用GPU硬件解码,并保存解码完的yuv文件。 其实,ffmpeg自带的例子hw_decode.c这个文件,就已经能满足要求了,因此,本文就尝试讲解以下hw_decode这个例子。hw_decode.c可以…

watchpoint

前言 内存被踩,通过 watchpoint 找到真凶 实例 以 smsc911x 网卡驱动为基体,进行实验,和网卡本身功能无关, 每执行一次 ifconfig eth0 up,就会调用一次 smsc911x_open(),我在这里设计了一段代码&#xf…

数学知识(四)(容斥原理、博弈论)

一、容斥原理 容斥原理公式 一共加或者减的式子个数 (一)利用容斥原理解决求能被质数整除的数的个数 890计算能被整除的数的个数 因为一共有2^n-1种选法,可以用位运算的方式枚举,对于得到的每一种选法,根据存在的数…

六、回归与聚类算法 - 逻辑回归与二分类

线性回归欠拟合与过拟合线性回归的改进 - 岭回归分类算法:逻辑回归模型保存与加载无监督学习:K-means算法 1、应用场景 2、原理 2.1 输入 2.2 激活函数 3、损失以及优化 3.1 损失 3.2 优化 4、逻辑回归API 5、分类的评估方法 5.1 精确率和召回率 5.2…

【Spring】IoC容器 控制反转 与 DI依赖注入 配置类实现版本 第四期

文章目录 基于 配置类 方式管理 Bean一、 配置类和扫描注解二、Bean定义组件三、高级特性:Bean注解细节四、高级特性:Import扩展五、基于注解配置类方式整合三层架构组件总结 基于 配置类 方式管理 Bean Spring 完全注解配置(Fully Annotatio…

Kotlin学习 6

1.接口 interface Movable {var maxSpeed: Intvar wheels: Intfun move(movable: Movable): String}class Car(var name: String, override var wheels: Int 4, _maxSpeed: Int) : Movable {override var maxSpeed: Int _maxSpeedget() fieldset(value) {field value}overr…

C语言读取 ini 配置文件,修改/添加键值对

C语言读取 ini 配置文件,修改/添加键值对 C语言读取 ini 配置文件,对section中的键值对进行修改/添加,如果section不存在,则在末尾将新的section/key/value 添加进去。 一、了解什么是INI文件? ini 文件是Initializ…

【大数据】Flink 之部署篇

Flink 之部署篇 1.概述和参考架构2.可重复的资源清理3.部署模式3.1 Application 模式3.2 Per-Job 模式(已废弃)3.3 Session 模式 Flink 是一个多用途框架,支持多种不同的混合部署方案。下面,我们将简要介绍 Flink 集群的构建模块、…

【html学习笔记】3.表单元素

1.文本框 1.1 语法 <input type "text">表示文本框。且只能写一行 1.2 属性 使用属性size 设置文本框大小 <input type"text" size"10">2. 使用属性value 来设置文本框的默认文字 <input type"text" size"…

Vue状态管理库-Pinia

一、Pinia是什么&#xff1f; Pinia 是 Vue 的专属状态管理库&#xff0c;它允许支持跨组件或页面共享状态&#xff0c;即共享数据&#xff0c;他的初始设计目的是设计一个支持组合式API的 Vue 状态管理库&#xff08;因为vue3一个很大的改变就是组合式API&#xff09;,当然这…

PFA三角烧瓶实验室PFA锥形瓶本底纯净耐腐蚀性强

PFA三角烧瓶外观呈平底圆锥状&#xff0c;下阔上狭&#xff0c;有一圆柱形颈部&#xff0c;上方有一较颈部阔的开口&#xff0c;可用塞子封闭。PFA三角烧瓶也称PFA锥形瓶&#xff0c;PFA反应瓶&#xff0c;PFA三角烧瓶、PFA依氏烧瓶、PFA锥形烧瓶&#xff0c;PFA鄂伦麦尔瓶等。…

普中51单片机学习(串口通信)

串口通信 原理 计算机通信是将计算机技术和通信技术的相结合&#xff0c;完成计算机与外部设备或计算机与计算机之间的信息交换 。可以分为两大类&#xff1a;并行通信与串行通信。并行通信通常是将数据字节的各位用多条数据线同时进行传送 。控制简单、传输速度快&#xff1…

【Python】Python实现串口通信(Python+Stm32)

&#x1f389;欢迎来到Python专栏~Python实现串口通信 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;Python学习专栏 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望…

springboot208基于springboot物流管理系统

基于spring boot物流管理系统设计与实现 摘 要 社会发展日新月异&#xff0c;用计算机应用实现数据管理功能已经算是很完善的了&#xff0c;但是随着移动互联网的到来&#xff0c;处理信息不再受制于地理位置的限制&#xff0c;处理信息及时高效&#xff0c;备受人们的喜爱。…

maven工程打包引入本地jar包

1、通过maven生成本地区仓库包 mvn install:install-file --settings D:\lkx\download\apache-maven-3.6.3\conf\settings.xml -Dfileaspose-cad-21.8.jar -DartifactIdaspose-cad -DgroupIdsystem.core -Dversion21.8 -Dpackagingjar -DgeneratePomtrue # --settings&#xf…

进程线程间的通信:2024/2/22

作业1&#xff1a;代码实现线程互斥机制 代码&#xff1a; #include <myhead.h>//临界资源 int num10;//创建一个互斥锁 pthread_mutex_t mutex;//任务一 void *task1(void *arg) {//获取锁资源pthread_mutex_lock(&mutex);num123;sleep(3);printf("task1:num…

PacketSender-用于发送/接收 TCP、UDP、SSL、HTTP 的网络实用程序

PacketSender-用于发送/接收 TCP、UDP、SSL、HTTP 的网络实用程序 PacketSender是一款开源的用于发送/接收 TCP、UDP、SSL、HTTP 的网络实用程序&#xff0c;作者为dannagle。 其官网地址为&#xff1a;https://packetsender.com/&#xff0c;Github源代码地址&#xff1a;htt…

SQL Server —— While语句循环

一&#xff1a;简介 while 循环是有条件的循环控制语句。满足条件后&#xff0c;再执行循环体中的SQL语句。 while: break, 如果有多条语句可以在while后面添加begin-end。关于while的语法 while(条件) -- begin -- 语句1 -- 语句2 -- break 根据情况是否添加break -- end 二…