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.hqwc.cn/news/485739.html

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

相关文章

通信入门系列——锁相环、平方环、Costas环

微信公众号上线,搜索公众号小灰灰的FPGA,关注可获取相关源码,定期更新有关FPGA的项目以及开源项目源码,包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 本节目录 一、锁相环 1、压控振荡…

设计模式-创建型模式-原型模式

原型模式(Prototype Pattern):使用原型实例指定创建对象的种类,并且通过克隆这些原型创建新的对象。原型模式是一种对象创建型模式。原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节…

初识表及什么是数据表

一、了解表 1.1.概述 表是处理数据和建立关系型数据库及应用程序的基本单元,是构成数据库的基本元素之一,是数据库中数据组织并储存的单元,所有的数据都能以表格的形式组织,目的是可读性强。 1.2.表结构简述 一个表中包括行和列…

C# OpenCvSharp 利用白平衡技术进行图像修复

目录 效果 灰度世界(GrayworldWB)-白平衡算法 完美反射(SimpleWB)-白平衡算法 基于学习的(LearningBasedWB)-白平衡算法 代码 下载 C# OpenCvSharp 利用白平衡技术进行图像修复 OpenCV xphoto模块中提供了三种不同的白平衡算法,分别是:灰度世界(G…

qml 保存当前界面并在其图片中添加文字

使用场景:在保存二维码的时候, 在二维码图片加标题或描述 保存后的图片 demo:https://download.csdn.net/download/uVarAndMethod/88868455

【AIGC】Gemma和ChatGLM3-6B使用体验

近期,谷歌发布了全新的开源模型Gemma,同时智谱AI和清华大学KEG实验室合作推出了ChatGLM3-6B。这两个模型都是先进的对话预训练模型,本文将对它们进行对比,并分享使用体验。 先上效果 ChatGLM3-6B: ChatGLM3 Gemma(20亿参数)&…

安全中国云 | 亚信安全与云宏完成产品互认 共筑云安全未来

近日,亚信安全与云宏信息科技股份有限公司(以下简称云宏)进一步强化云上合作,完成多款产品兼容性互认。亚信安全云主机安全产品(DeepSecurity)与云宏CNware WinSphere服务器虚拟化软件、CNware WinStack虚拟…

【嵌入式学习】QT-Day2-Qt基础

1> 思维导图 https://lingjun.life/wiki/EmbeddedNote/20QT 2>登录界面优化 使用手动连接,将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中,在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff…

解决IDEA git 提交慢的问题

文章目录 前言解决IDEA git 提交慢的问题 前言 如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!! 解…

LeetCode 热题 100 | 二叉树(终)

目录 1 二叉树小结 1.1 模式一 1.2 模式二 2 236. 二叉树的最近公共祖先 3 124. 二叉树中的最大路径和 菜鸟做题(返校版),语言是 C 1 二叉树小结 菜鸟碎碎念 通过对二叉树的练习,我对 “递归” 有了一些肤浅的理解。…

详解NLP多任务统一框架T5:揭秘T5的全能之谜

Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer 1910.10683.pdf (arxiv.org) 1.Abstract 预训练可以让模型学习到可以被迁移到下游任务重的通用能力和知识。在迁移学习中,模型首先在数据丰富的任务上进行预训练&#xff0c…

AI绘画与修图:重塑数字艺术的新纪元

文章目录 一、AI绘画与修图的原理二、AI绘画的应用三、AI修图的优势四、面临的挑战五、未来发展趋势《AI绘画与修图实战:PhotoshopFirefly从入门到精通 轻松玩转AI绘画与修图实战》亮点内容简介作者简介 随着人工智能技术的飞速发展,AI绘画与修图已经成为…