Spring之AOP源码解析(下)

前言

在上一遍文章中,我们主要讲解了ProxyFactory在Spring完成AOP动态代理的过程中发挥的作用。这一篇我们主要讲解这些注解都是如何注入Advisors,然后分析这些Advisors生效的条件

注解都是如何注入Advisor并匹配的

@EnableTransactionManagement注解

我们在之前提到@EnableTransactionManagement注解会注入一个类型为InfrastructureAdvisorAutoProxyCreator的bpp和事务相关的bean

ProxyTransactionManagementConfiguration这个配置类会注入一个类型为BeanFactoryTransactionAttributeSourceAdvisor的Advisor(以bean的方式注入)

InfrastructureAdvisorAutoProxyCreator这个bpp在执行postProcessAfterInitialization方法的时候会查找可以对bean增强的Advisor,如果找到合适的Advisor则会通过进行aop动态代理

目前这些内容我们在之前的文章中都分析了,现在我们重点关注findAdvisorsThatCanApply这个方法 

 当我们不清楚这个Pointcut是什么类型的时候,可以debug看一下

通过debug我们发现Pointcut是@EnableTransactionManagement注解注入的Advisor的匿名内部类

我们查看这个Advisor的类结构

所以这个Pointcut是一个TransactionAttributeSourcePointcut的一个实例对象

我们再查看TransactionAttributeSourcePointcut的类结构

通过以上分析我们小结一下

  • Pointcut的类型为TransactionAttributeSourcePointcut
  • TransactionAttributeSourcePointcut的过滤器类型为TransactionAttributeSourceClassFilter
  • TransactionAttributeSourcePointcut的MethodMatcher为其自身,并且不等于MethodMatcher.TRUE,且不属于IntroductionAwareMethodMatcher

所以最终我们只需要关注TransactionAttributeSourcePointcut的matches是否能匹配成功

TransactionAttributeSourcePointcut#matcheAbstractFallbackTransactionAttributeSource#getTransactionAttribute AbstractFallbackTransactionAttributeSource#computeTransactionAttributeAnnotationTransactionAttributeSource#findTransactionAttribute 
AnnotationTransactionAttributeSource#determineTransactionAttributeSpringTransactionAnnotationParser#parseTransactionAnnotation

综上所述:@EnableTransactionManagement会注入一个类型为BeanFactoryTransactionAttributeSourceAdvisor的Advisor,当spring处理其他普通bean的时候,这个Advisor就会判断这个bean是否满足自己进行增强的条件(bean含有@Transactional注解标注的方法或者类上含有@Transactional注解),如果满足条件,spring在后期就会进行AOP动态代理

@EnableAspectJAutoProxy注解

从前面两篇文章中我们分析得出@EnableAspectJAutoProxy会注入一个类型为AnnotationAwareAspectJAutoProxyCreator的bpp,这个bpp重写了findCandidateAdvisors方法,我们以这个方法为切入口,分析方法是如何增强的

AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisorsBeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisorsReflectiveAspectJAdvisorFactory#getAdvisorsReflectiveAspectJAdvisorFactory#getAdvisorReflectiveAspectJAdvisorFactory#getPointcutAbstractAspectJAdvisorFactory#findAspectJAnnotationOnMethod

 综上所述:@EnableAspectJAutoProxy注入的bpp会额外查找一些符合条件的Advisor,相关条件如下

  1. bean所属的class上含有@Aspect注解
  2. 存在含有@Around,@Before,@After,@AfterReturning,@AfterThrowing标注的方法

查找出的对象被封装成InstantiationModelAwarePointcutAdvisorImpl,接下来的判断逻辑和@EnableTransactionManagement注解是一致的,都是利用AopUtils的canApply方法,我们需要搞清楚下列几个点,其他细节读者可以自行翻阅源码

  1. InstantiationModelAwarePointcutAdvisorImpl的getPointcut方法返回的是AspectJExpressionPointcut
  2. AspectJExpressionPointcut的getClassFilter方法返回的是自身
  3. AspectJExpressionPointcut的getMethodMatcher方法返回的也是自身
  4. AspectJExpressionPointcut的matches方法的匹配细节

小结

@EnableAspectJAutoProxy注入的bpp通过重写findCandidateAdvisors方法,查找出更多的Advisors,每个Advisor都会通过getPointcut方法返回一个Pointcut对象,Pointcut有两个待实现的方法(getClassFilter、getMethodMatcher),spring会先通过getClassFilter方法返回一个Filter来判断目标类是否满足需求,然后再通过getMethodMatcher方法返回一个MethodMatcher对象,如果MethodMatcher对象等于MethodMatcher.TRUE则直接返回true,否则就获取目标类的相关方法,如果存在一个方法满足MethodMatcher的matches方法,则表示这个Advisor可以作用在这个目标类上。如果存在满足条件的Advisor,spring会在后续进行AOP动态代理

@EnableAsync注解

在前文我们分析得出@EnableAsync会注入一个类型为AsyncAnnotationBeanPostProcessor的bpp,我们查看这个类的类结构,获取一些前提条件

1.无参构造函数

作用:将属性beforeExistingAdvisors设置为true 

2.回调方法setBeanFactory

作用:给属性advisor赋值

AsyncAnnotationBeanPostProcessor作为一个bpp,其主要动态代理相关源码在其祖父类的postProcessAfterInitialization方法中,我们来看看相关明细

小提示:在Spring之AOP源码解析(中)这篇文章中我们分析了,如果通过设置的参数,spring最终决定进行jdk动态代理,则会实现SpringProxy,Advised,DecoratingProxy这三个默认接口,否则会实现SpringProxy,Advised这两个默认接口,所以被spring动态代理的类一定实现Advised接口

我们继续查看这个isEligible方法(通过方法调用,获取最里层方法)

我们又看到这个熟悉的canApply方法,判断流程同上,我们需要知道这个advisor的类型为AsyncAnnotationAdvisor,关注相关方法细节就可以了

我将上述三个注解在Spring中的执行时机用时序图展示出来,便于大家更好的理解

说明一下

  1. 步骤1~6顺序可能不固定,但是最终结果是一样的(存在两个bpp和一个advisor)
  2. 步骤13~14是@EnableTransactionManagement(@EnableAspectJAutoProxy)注入的bpp可能产生的两种结果
  3. 步骤17~18是@EnableAsync注入的bpp对于步骤13可能产生的两种结果
  4. 步骤19~20是@EnableAsync注入的bpp对于步骤14可能产生的两种结果

Spring容器启动后,调用代理对象流程

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

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

相关文章

C++ const关键字

在C中,const是一个关键字,用于声明常量或者修饰变量、指针、引用等,表示其数值是不可修改的。const关键字的主要作用包括一下几个方面: 一、修饰基本数据类型 基本数据类型,修饰符const可以用在类型说明符前&#xf…

STM32 TCP实现OTA

芯片:stm32f407 开发平台:stm32cubeide 上位机开发平台:visual studio 2017 1. FLASH分配 将flash划分为四个部分: bootloader: 0x8000000-0x800ffff app1: 0x8010000-0x805ffff app2: …

一流的财务:搞数据!!!(干货)

“三流财务给数据,二流财务给分析报告,一流财务给....(解决方案)“这些文章应该很多人都看到过,这个口号粗看好像很有道理,但笔者并不认同,因为大家都忽略了一个重要的概念:数据&…

什么是rouge metric

采用分类任务的指标评估生成任务的问题 举个例子,在一个seq2seq模型中,黄金标签是“police killed the gunman”,模型输出是"the gunman police killed",两句话的意思是有差别的,但是从unigram的角度&#…

数字化浪潮下的企业变革:深度解析ERP的崭新篇章

引言: 随着科技的飞速发展,企业正迎来前所未有的数字化浪潮。在这个数字时代,企业资源规划(ERP)被认为是企业应对挑战、实现创新的重要工具。本文将深入研究ERP的发展历程,聚焦不同行业和场景下的创新应用…

Atomic-flag-tutorial

本文介绍 <atomic> 头文件中最简单的原子类型: atomic_flag。atomic_flag 一种简单的原子布尔类型&#xff0c;只支持两种操作&#xff0c;test_and_set 和 clear。 std::atomic_flag 详解 std::atomic_flag 构造函数 std::atomic_flag 构造函数如下&#xff1a; ato…

ROS2 学习笔记13:创建 ROS2 包

ROS2 学习笔记13&#xff1a;创建 ROS2 包 Background 背景1 什么是ROS2 包2 ROS2包的组成3 工作空间的包 Prerequisites 前提Tasks 任务1 Create a package2 Build a package3 Source the setup file4 Use the package5 Examine package contents6 Customize package.xml Summ…

虚 拟 化原理

1 概念&#xff1a; ①通俗理解&#xff1a; 虚拟化是在硬件和操作系统之间的实践 ②通过对计算机的服务层级的理解&#xff0c;理解虚拟化概念 抽离层级之间的依赖关系&#xff08;服务器虚拟化&#xff09; 2 虚拟化分类 ①按架构分类 ◆寄居架构&#xff1a;装在操作系统上…

pytest.param作为pytest.mark.parametrize的参数进行调用

pytest.param&#xff1a;在 pytest.mark.parametrize 中可以作为一个指定的参数进行调用 获取数据库&#xff08;网页端&#xff09;数据&#xff0c;通过pytest.param包装成数据包用于pytest.mark.parametrize 中实现数据驱动调用。 import os import pytest import json fr…

OSCP靶场--Nickel

OSCP靶场–Nickel 考点(1.POST方法请求信息 2.ftp&#xff0c;ssh密码复用 3.pdf文件密码爆破) 1.nmap扫描 ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.237.99 -sV -sC -p- --min-rate 5000 Starting Nmap 7.92 ( https://nmap.org ) at 2024-02-22 04:06 EST Nm…

5.1 Ajax数据爬取之初介绍

目录 1. Ajax 数据介绍 2. Ajax 分析 2.1 Ajax 例子 2.2 Ajax 分析方法 &#xff08;1&#xff09;在网页页面右键&#xff0c;检查 &#xff08;2&#xff09;找到network&#xff0c;ctrl R刷新 &#xff08;3&#xff09;找 Ajax 数据包 &#xff08;4&#xff09;…

【前后端的那些事】文件上传组件封装

文章目录 效果前端代码后端代码组件封装 效果 前端代码 /views/file/file.vue <template><el-row><el-uploadv-model:file-list"fileList"class"upload-demo"multiple:auto-upload"false":on-preview"handlePreview"…

Javascript[ECMAScript] ES6、ES7、ES8、ES9、ES10、ES11、ES12、ES13、ES14[2023]新特性

# 前言 鉴于找不到ES6-ES14 的新特性集合&#xff0c;所以有了这篇文章&#xff0c;后续会持续更新每年的新特性 # 背景 ## JS1.1&#xff08;1997&#xff09; [第一版基于Netscape Navigator 3.0中实现的JAVASCRIPT 1.1](https://web.archive.org/web/19970614042441/http:/…

数据结构之:跳表

跳表&#xff08;Skip List&#xff09;是一种概率性数据结构&#xff0c;它通过在普通有序链表的基础上增加多级索引层来实现快速的查找、插入和删除操作。跳表的效率可以与平衡树相媲美&#xff0c;其操作的时间复杂度也是O(log n)&#xff0c;但跳表的结构更简单&#xff0c…

Swiper.js:不识这个轮播图js库,说明你的前端还未入门

hello&#xff0c;我是贝格前端工场&#xff0c;本期给大家带来轮播图的s库&#xff1a;Swiper.js&#xff0c;用这个类库处理轮播图、幻灯片、画廊那是得心应手&#xff0c;非常的easy&#xff0c;欢迎老铁们点赞关注&#xff0c;如有前端定制开发需求可以私信我们。 一、Swip…

网络编程、UDP、TCP

计算机网络 就是将地理位置不同的具有独立功能的多台计算及外部设备&#xff0c;通过通信线路连接起来&#xff0c;在网络操作系统、网络管理软件以及网络通信协议的管理和协调下&#xff0c;实现资源共享和信息传递的计算机系统 目的 传播交流信息、数据交换、通信 如何做…

TensorRT及CUDA自学笔记003 CUDA编程模型、CUDA线程模型及其管理、CUDA内存模型及其管理

TensorRT及CUDA自学笔记003 CUDA编程模型、CUDA线程模型及其管理、CUDA内存模型及其管理 各位大佬&#xff0c;这是我的自学笔记&#xff0c;如有错误请指正&#xff0c;也欢迎在评论区学习交流&#xff0c;谢谢&#xff01; CUDA编程模型 我们使用CUDA_C语言进行CUDA编程&am…

【Vue3】‘vite‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。

问题 今天拿到别人项目的时候&#xff0c;我平时比较习惯用pnpm&#xff0c;我就使用pnpm i先下载依赖包&#xff0c;下载完成后&#xff0c;启动项目&#xff0c;就开始报以下错误&#xff01; 但是当我执行pnpm i的时候&#xff0c;vite不应该就已经被我下载下来了吗 研究了…

学习JAVA的第五天(基础)

目录 API 字符串 String概述 比较的是什么&#xff1f; 关于字符串的比较 字符串代码展示 StringBuilder概述 StringBuilder方法的代码展示 StringJoiner概述 StringJoiner方法的代码展示​​​​​​​ 练习-用户登录 API API&#xff08;Application Programing I…

【Java程序设计】【C00307】基于Springboot的基Hadoop的物品租赁管理系统(有论文)

基于Springboot的基Hadoop的物品租赁管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的基于 Hadoop的物品租赁系统的设计与实现&#xff0c;本系统有管理员、用户二种角色权限&#xff1b; 前台首页&#…