Spring Aop 源码增强获取分享
作者:? 发布时间:2023-06-22 21:59:22
1 前言
在前文中,已经讲述了 AOP 的后置处理器使用和方法,在本文中继续分享增强信息相关的源码,这里才是 AOP 的核心代码。
2 spring 增强器
之前已经讲述了 spring AbstractApplicationContext.refresh
方法,在以下方法中都会处理会处理 BeanPostProcessor
接口。
invokeBeanFactoryPostProcessors
registerBeanPostProcessors
finishBeanFactoryInitialization
增强器的获取,就是提取 @Aspect
注解标记的内容,这个操作一般是在后置处理器中进行处理,在 refresh 方法中调用 finishBeanFactoryInitialization
步骤中进行实现,最终可以追溯到 AbstractAutoProxyCreator.postProcessAfterInitialization
。Spring 容器中注册的 AnnotationAwareAspectJAutoProxyCreator
父类就是 AbstractAutoProxyCreator
,继而调用 postProcessBeforeInstantiation
方法获取代理对象。
在实例化之后,初始化之后会调用 postProcessAfterInitialization
方法,
如下图所示:
如果有 @Aspect
注解的切面,则将通过 AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
方法进行获取并放入缓存中。
这里的 findCandidateAdvisors
方法的解析和追踪,获取增强器需要追踪 AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors()
方法,其又调用了 BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors()
方法,主要的作用就是为了获取切面逻辑,即获取增强器。
在这里
this.advisorFactory.getAdvisors(factory)
是获取增强器的最终实现方法,在 ReflectiveAspectJAdvisorFactory
工程方法中,可以看到以下内容,这里采用的是委托模式:
以上是获取增强器的核心逻辑,对于如何解析切面逻辑的注解,则还需要从以下方法进行着手分析,主要就是 getPointcut
方法。
在该方法中,主要实现了以下功能:
1 获取切点的信息,切点信息一般是指获取注解表达式的信息。
2 根据切点信息生成增强实现,所有的实现类都由
InstantiationModelAwarePointcutAdvisorImpl
进行统一的封装。
这里的 instantiateAdvice
方法即是获取切面逻辑
invokeAdviceMethod
这个方法就是实际调用的方法。
findCandidateAdvisors
查找所有的增强器的解析,但是对于所有的增强器,不一定能适用于当前 Bean,还需要挑选适合的增强器,满足配置的通配符的增强器。这就用到了 findAdvisorsThatCanApply
。
BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors()
来获取所有的 Advisor。其核心逻辑如下图所示:
1 获取所有的 beanName,这个 Spring 提供了
BeanFactoryUtils.beanNamesForTypeIncludingAncestors
方法来获取容器中所有的 beanName 信息。2 遍历所有的 beanName , 并找出声明有 AspectJ 注解的类。
3 对标记为 AspectJ 注解的类进行增强器的提取。
4 将提取增强的结果放入 advisorsCache 中。
以上便是获取增强器的全部过程,总结来说 wrapIfNecessary
getAdvicesAndAdvisorsForBean
buildAspectJAdvisors
都是核心的方法。
3 总结
本文讲了获取增强信息获取的源码,主要核心方法为wrapIfNecessary
getAdvicesAndAdvisorsForBean
buildAspectJAdvisors
,在后续文中将继续 AOP 代码的分享。
来源:https://juejin.cn/post/7087465088617021448


猜你喜欢
- 在移动端,各个平台或 UI 系统的原始指针事件模型基本都是一致,即:一次完整的事件分为三个阶段:手指按下、手指移动、和手指抬起,而更高级别的
- 本文介绍了Java实现动态获取图片验证码的示例代码,分享给大家,具体如下:import javax.imageio.ImageIO;impo
- 一、定时任务1、cron表达式语法:秒 分 时 日 月 周 年(其中“年”Spring不支持,也就是说在spring定时任务中只能设置:秒
- session对象用于在会话范围内,记录每个客户端的访问状态,以便于跟踪每个客户端的操作状态,在会话存储的信息,在浏览器发出后续请求时可以获
- state:比较常用,各种状态都可以用它,但是它更着重于一种心理状态或者物理状态。Status:用在人的身上一般是其身份和地位,作“状态,情
- 先执行以一个简单的示例:static void Main(string[] args) { &nb
- 一、稀疏数组1、什么是稀疏数组当一个数组中大部分元素为0,或者为同一个值的数组时,可以用稀疏数组来保存该数组。稀疏数组,记录一共有几行几列,
- Android Studio第一次启动的Fetching android sdk component information的问题1)进入刚
- 一、首先进行Server的编写:public class SocketServer { private static Socket mSoc
- 开始学习WebSocket,准备用它来实现一个在页面实时输出log4j的日志以及控制台的日志。首先知道一些基础信息:1.java7 开始支持
- 这只是初步的实现,并没有加入自动编译等功能。需要手动更改更新的xml文件和最新的apk。 共涉及到四个文
- 一、实验题目二、分析实验要求为:实现一个界面,界面中包含一个文本显示区和两个按钮(存档和读档)读档按钮作用是打开文件并读取内容,将内容显示在
- 表述在一次服务更新后发现每天凌晨0点3秒服务准时挂,开始的时候认为是maven依赖中存在system.exit(3)类似这样的代码,但是我想
- 项目前端由于采用Extjs4,列表分页需要返回三个参数:totalCount(记录总数)、start(开始位置)、limit(每页条数)。由
- 前言首先,我们要讲的是JVM的垃圾回收机制,我默认准备阅读本篇的人都知道以下两点:JVM是做什么的Java堆是什么因为我们即将要讲的就是发生
- 本文实例讲述了C#实现的文件压缩和解压缩类。分享给大家供大家参考。具体分析如下:这个C#代码包含了几个类,封装了文件压缩和解压缩常用的方法,
- 摘要:这个问题算是老生常谈了,我也是一段时间没弄过了,所以感觉有些忘了,就记录一下。一、后端通过shiro在session中存储数据://
- 本来是想写一篇《委托与lambda表达式的前世今生》,但仅委托部分已经写了很多内容,于是就此分开关于Lambda表达是的内容后续再写吧。不知
- 本文所述为基于C#实现的端口扫描器代码,代码内包括了窗体和逻辑处理两部分代码。在代码中,创建TcpClient对象,把TcpClient用于
- 1, 泛型接口的协变如果泛型类型用out关键字标注,泛型接口就是协变的。这也意味着返回类型只能是T。泛型接口的抗变如果泛型类型用in关键字标