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容器启动后,调用代理对象流程

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

乡村研学|乡村研学小程序|基于微信小程序的乡村研学平台设计与实现(源码+数据库+文档)

乡村研学小程序目录 目录 基于微信小程序的乡村研学平台设计与实现 一、前言 二、系统功能设计 三、系统实现 1、微信小程序前台 2、管理员后台 (1)乡村研学管理 (2)商品信息管理 (3)商品类型管理 …

计算机网络:思科实验【2-MAC地址、IP地址、ARP协议及总线型以太网的特性】

🌈个人主页:godspeed_lucip 🔥 系列专栏:Cisco Packet Tracer实验 本文对应的实验报告源文件请关注微信公众号程序员刘同学,回复思科获取下载链接。 实验目的实验环境实验内容MAC地址、IP地址、ARP协议总线型以太网的…

【DAY04 软考中级备考笔记】数据结构基本结构和算法

数据结构基本结构和算法 2月25日 – 天气:晴 周六玩了一天,周天学习。 1. 什么是数据结构 数据结构研究的内容是一下两点: 如何使用程序代码把现实世界的问题信息化如何用计算机高效地处理这些信息从创造价值 2. 什么是数据 数据是信息的…

零基础C++开发上位机--基于QT5.15的串口助手(一)

嵌入式开发的过程中,大部分我们的代码是无法一次成功的。这时候我们大部分的工程师可能最熟练的调试方法是printf函数,打印随意一个数据,来观察当前运行的函数是否执行正确。我们连接的工具有各个大神做的串口助手。另外,在做一般…

从0开始python学习-53.python中flask创建简单接口

目录 1. 创建一个简单的请求,没有写方法时默认为get 2. 创建一个get请求 3. 创建一个post请求,默认可以使用params和表单传参 4. 带有参数的post请求 1. 创建一个简单的请求,没有写方法时默认为get from flask import Flask, request# 初始化一个flask的对象 ap…

【贪心算法】:LeetCode860.柠檬水找零

朋友们、伙计们,我们又见面了,本专栏是关于各种算法的解析,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏:C语言:从入门到精通 数据结构专栏&…

Ubuntu22.04和Windows10双系统安装

概要 本篇演示Ubuntu22.04和Windows10双系统的安装。先安装Ubuntu22.04,再安装Windows10。 一、说明 1、电脑 笔者的电脑品牌是acer(宏碁/宏基) 电脑开机按F2进入BIOS 电脑开机按F12进入Boot Manager 2、U盘启动盘 需要用到两个U盘启动盘 (1&a…

kubernetes集群搭建(1.26版本)

集群搭建 1.初始化安装k8s集群的实验1.1修改主机名称1.2关闭防火墙1.3关闭SELINUX1.4配置主机hosts文件,相互之间通过主机名访问1.5配置主机之间无密码登录1.6关闭交换分区swap,提升性能1.7修改机器内核参数1.9配置阿里云的repo源1.10配置安装k8s组件需要…

力扣● 343. 整数拆分 ● 96.不同的二叉搜索树

● 343. 整数拆分 想不到,要勇于看题解。 关键在于理解递推公式。 1、DP数组及其下标的含义:dp[i]是分解i这个数得到的最大的乘积。 2、DP数组如何初始化:dp[0]和dp[1]都没意义,所以直接不赋值,初始化dp[2]1即可。…

让程序员设计B端界面,好比武大郎招聘:向我看齐。不忍直视!

hello,我是大美B端工场,B端系统的要求越来越高了,很多公司还让程序员负责页面,页面搞的没法看,也怪不得程序员。程序员来搞页面,那还不是武大郎招聘——向我看齐,以我的标准为标准吗&#xff1f…

python 基础知识点(蓝桥杯python科目个人复习计划49)

今日复习内容:做复习题 例题1:希尔排序 题目描述: 希尔排序是直接插入排序算法的一种更高效的改进版本,但它是非稳定排序算法。希尔排序是基于插入排序的以下两点性质而提出的改进方法之一: 1.插入排序在对几乎已经…

预训练-微调范式在人工智能领域的深远影响

预训练-微调范式的出现是人工智能领域的一大里程碑,它深刻改变了深度学习模型的训练方式和应用模式,并对整个行业产生了多方面的深远影响: 数据效率提升: 通过在大规模无标注数据上进行预训练,模型能够学习到丰富的语言…

linux常用的网络命令实战分享

文章目录 ifup/down命令ifconfig命令观察网络接口信息修改接口参数增加虚拟网络接口 route命令查看路由表增加路由表规则删除路由表规则 IP 命令ip linkip addr设定路由 ip route arp 命令 在实际研发运维工作中常常会涉及到网关相关的操作和知识,这里对linux下常用…

(详细使用指南)Linux下交叉编译带ffmpeg的opencv并移植到RK3588等ARM端

一 问题背景 瑞芯微RK3588等嵌入式板作为边缘端设备为算法模型的部署提供了便利,目前很多分类或好检测模型针对边缘端做了优化或量化,使得在边缘端也能达到实时稳定的识别和检测效果。 但嵌入式设备普遍的flash emmc不大,一般在32G左…

【数据结构与算法】(20)高级数据结构与算法设计之 Greedy Algorithm 贪心算法 代码示例与详细讲解

目录 4.2 Greedy Algorithm1) 贪心例子DijkstraPrimKruskal 2) 零钱兑换问题有几个解(零钱兑换 II)Leetcode 518最优解(零钱兑换)- 穷举法 Leetcode 322最优解(零钱兑换)- 贪心法 Leetcode 322 3) Huffman …

9.5K Star,又一款超棒开源轻量自动化运维平台

Hi,骚年,我是大 G,公众号「GitHub指北」会推荐 GitHub 上有趣有用的项目,一分钟 get 一个优秀的开源项目,挖掘开源的价值,欢迎关注。 一个好的运维平台就变得非常重要了,可以节省大量的人力和物…

【HarmonyOS】低代码开发—使用低代码开发服务卡片

DevEco Studio还支持使用低代码开发功能开发服务卡片,目前只支持JS语言,且compileSdkVersion必须为7或以上。 下面以创建一个新的服务卡片为例进行说明。 1.打开一个工程,创建服务卡片,创建方法包括如下两种方式: 选…

SpringBoot自带的tomcat的最大连接数和最大的并发数

先说结果:springboot自带的tomcat的最大并发数是200, 最大连接数是:max-connectionsaccept-count的值 再说一下和连接数相关的几个配置: 以下都是默认值: server.tomcat.threads.min-spare10 server.tomcat.threa…

老隋蓝海项目temu跨境电商好不好做?

近年来,跨境电商成为我国对外贸易的新亮点,其中Temu作为拼多多旗下的新兴跨境电商平台,吸引了众多国内卖家参与。老隋作为行业内的知名人士,他对Temu跨境电商项目的评价备受关注。本文将分析老隋对Temu跨境电商的看法,…

RDMA内核态函数ib_post_send()源码分析

最近调用linux内核下RDMA的Verb API ib_post_send()出现了问题,因此从源码分析一下这个函数的调用过程。 我使用的内核版本为5.15.0-94 这是函数ib_post_send的头文件定义,这个函数的意义是向发送队列提交发送请求,他会调用qp对应设备的post_…