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.rhkb.cn/news/263825.html

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

相关文章

【Java程序设计】【C00290】基于Springboot的网上书城管理系统(有论文)

基于Springboot的网上书城管理系统(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的网上书城管理系统 本系统分为系统功能模块、管理员功能模块以及用户功能模块。 系统功能模块:在系统首页可以查看首…

Day07-面向对象-封装课后练习以及参考答案

文章目录 巩固题包练习成员变量基础题第1题:员工第2题:日期类 成员方法基础题第3题:三角形第4题:日期类第5题:数组工具类 拔高题第6题:公民类第7题:数组工具类 巩固题 包练习 每道作业题可以单…

12 个顶级音频转换器软件(免费)

当涉及不受支持的音乐文件时,音频文件转换器软件总是会派上用场。当您希望缩小大量大型音乐文件的大小以节省设备存储空间时,它也很有帮助。您在寻找传输音频的软件吗?好吧,请仔细选择音频转换器,因为最好的音乐转换器…

C语言数据存储

目录 一.数据类型的介绍 (1)整形家族 (2)浮点型家族 (3)构造类型 (4)其他 二.整形在内存中如何进行存储 (1)原,反,补 &#xf…

《Docker 简易速速上手小册》第1章 Docker 基础入门(2024 最新版)

文章目录 1.1 Docker 简介与历史1.1.1 Docker 基础知识1.1.2 重点案例:Python Web 应用的 Docker 化1.1.3 拓展案例 1:使用 Docker 进行 Python 数据分析1.1.4 拓展案例 2:Docker 中的 Python 机器学习环境 1.2 安装与配置 Docker1.2.1 重点基…

k8s-hpa控制器 16

hpa可通过metrics-server所提供pod的cpu或者内存的负载情况,从而动态拉伸控制器的副本数,从而达到后端的自动弹缩 官网:https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscalewalkthrough/ 上传镜像 创建hpa实例 …

Java语言实现学生成绩排序问题

目录 题目: 代码展示: Student类 TestStudent类 运行结果 ​编辑 题目: 给定一段字符串,里面包含若干个学生上机和笔试成绩如 String str "张三:上机成绩90,笔试成绩78; 李四:上机成绩68,笔试成绩98; …

React18源码: reconcliler启动过程

Reconcliler启动过程 Reconcliler启动过程实际就是React的启动过程位于react-dom包&#xff0c;衔接reconciler运作流程中的输入步骤.在调用入口函数之前&#xff0c;reactElement(<App/>) 和 DOM对象 div#root 之间没有关联&#xff0c;用图片表示如下&#xff1a; 在启…

反序列化字符串逃逸 [安洵杯 2019]easy_serialize_php1

打开题目 $_SESSION是访客与整个网站交互过程中一直存在的公有变量 然后看extract()函数的功能&#xff1a; extract($_POST)就是将post的内容作为这个函数的参数。 extract() 函数从数组中将变量导入到当前的符号表(本题的作用是将_SESSION的两个函数变为post传参) function…

C++ //练习 8.9 使用你为8.1.2节(第281页)第一个练习所编写的函数打印一个istringstream对象的内容。

C Primer&#xff08;第5版&#xff09; 练习 8.9 练习 8.9 使用你为8.1.2节&#xff08;第281页&#xff09;第一个练习所编写的函数打印一个istringstream对象的内容。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /*****…

爬虫知识--03

数据存mysql import requests from bs4 import BeautifulSoup import pymysql# 链接数据库pymysql conn pymysql.connect(userroot,password"JIAJIA",host127.0.0.1,databasecnblogs,port3306, ) cursor conn.cursor() cursor conn.cursor()# 爬数据 res request…

ChatGPT Plus遇到订阅被拒原因与解决方案

ChatGPT Plus被广泛认为相比普通版本更快、更强&#xff0c;并且能最先体验新功能。 很多小伙伴再订阅时遇到图片中的问题 错误提示包括这些&#xff1a; Your credit card was declined.Try paying with a debit card instead.您的信用卡被拒绝了。请尝试用借记卡支付。你的…

Android 圆环带刻度条进度动画效果实现

效果图 需求是根据传感器做一个重力球效果&#xff0c;先实现了动画后续加上跟传感器联动. 又是摆烂的一天&#xff0c; 尚能呼吸&#xff0c;未来可期啊 View源码 package com.android.circlescalebar.view;import android.content.Context; import android.content.res.Typ…

【Crypto | CTF】BugKu 简单的RSA

天命&#xff1a;这题也不算简单了&#xff0c;要反编译&#xff0c;要灵活一点 首先收到pyc文件&#xff0c;拿去反编译出来&#xff0c;可以用在线反编译&#xff0c;也可以用工具反编译 在线&#xff1a;python反编译 - 在线工具 工具&#xff1a;https://download.csdn.n…

RocketMQ快速实战以及集群架构原理详解

RocketMQ快速实战以及集群架构原理详解 组成部分 启动Rocket服务之前要先启动NameServer NameServer 提供轻量级Broker路由服务&#xff0c;主要是提供服务注册 Broker 实际处理消息存储、转发等服务的核心组件 Producer 消息生产者集群&#xff0c;通常为业务系统中的一个功…

华清远见作业第四十一天——Qt(第三天)

思维导图&#xff1a; 编程 完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如…

利用iSCSI服务部署IP SAN网络存储服务

一、配置环境&#xff08;Vmware WorkStation虚拟环境&#xff09; 服务端与客户端OS&#xff1a;openEuler 22.03-LTS CPU&#xff1a;1U1C 内存&#xff1a;2G 硬盘&#xff1a;5个SCSI磁盘&#xff0c;其中一个作为系统盘&#xff0c;另外四个配置为RAID5阵列 服务器IP…

【黑马程序员】1、TypeScript介绍_黑马程序员前端TypeScript教程,TypeScript零基础入门到实战全套教程

课程地址&#xff1a;【黑马程序员前端TypeScript教程&#xff0c;TypeScript零基础入门到实战全套教程】 https://www.bilibili.com/video/BV14Z4y1u7pi/?share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 目录 1、TypeScript介绍 1.1 TypeScript是什…

React 模态框的设计(三)拖动组件的完善

我在上次的Draggable组件的设计中给了一个简化的方法&#xff0c;今天我来完善一下这个组件&#xff0c;可用于任何可移动组件的包裹。完善后的效果如下所示&#xff1a; 这个优化中&#xff0c;增加了一个注目的效果&#xff0c;还增加了触发可拖动区域的指定功能&#xff0c;…

pikachu靶场-RCE

介绍&#xff1a; RCE(remote command/code execute)概述 RCE漏洞&#xff0c;可以让攻击者直接向后台服务器远程注入操作系统命令或者代码&#xff0c;从而控制后台系统。 远程系统命令执行 一般出现这种漏洞&#xff0c;是因为应用系统从设计上需要给用户提供指定的远程命…