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
猜你喜欢
- 基本概念 * (Listener): * 用于监听web应用中某些对象、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处
- java实现读取、删除文件夹下的文件package test.com;import java.io.File;import java.io.
- 目的官方的Drools范例大都是基于纯Java项目或Maven项目,而基于Spring Boot项目的很少。本文介绍如何在Spring Bo
- 本文实例为大家分享了android桌面悬浮窗,实现录屏时间控制显示效果的具体代码,供大家参考,具体内容如下悬浮窗效果如上图所示:很简单的一个
- C# 中可以将类、结构或接口的定义拆分到两个或多个源文件中,在类声明前添加partial关键字即可。1. 什么是局部类型?C# 2.0 引入
- 字符串和列表学完,自己试着写了一个非常简单的Python名片管理系统。新萌尝试,大佬们不要喷。修改名片的功能我偷了个懒,因为我不知道怎么通过
- RocketMQ修改生产者消费者日志保存路径rocket默认是将所有日志文件保存到user.home的对于win系统就是C盘了。1.修改Ro
- 不过在实际的工作中,很少会直接用到它。通常都是用的spring-quartz组件,直接通过配置,让spring框架来自动装配如下就是spri
- 系统需要用到一个导入excel文件的功能,使用poi组件常规方式读取excel时,内存耗尽,OutOfMemoryError,或者读取非常慢
- 工作中一直都是一个人奋战一人一个项目,使用maven管理,看这个也挺好,但是总感觉没有充分发挥maven的功能,于是研究了一下这个,网上关于
- 1 前言敏感词过滤就是你在项目中输入某些字(比如输入xxoo相关的文字时)时要能检测出来,很多项目中都会有一个敏感词管理模块,在敏感词管理模
- 1.项目介绍这是一款基于 Java 开发的移动端安卓小游戏——大家来拼图2.项目原理把选定的一张图片
- 二维码是什么二维码 QR Code,全称为:Quick Response Code,最早用于日本汽车制造业追踪零部件。QR现有40个标准版本
- 自定义log4j日志文件命名规则项目中的日志需要采用一致的命名规范和文件规范,命名规则为:项目模块标识_index_日期时间_日志级别.lo
- 读取文本文件中的内容此示例读取文本文件的内容以使用 System.IO.File 选件类的静态方法 ReadAllText 和 ReadAl
- “无论是什么类型,所有的数据都是一系列的位,即一系列0和1。变量的含义是通过解释这些数据的方式来传达的。”——这句原话是书上翻译的,不过后一
- ODT文档格式一种开放文档格式(OpenDocument Text)。通常,ODT格式的文件可以使用LibreOffice Writer、M
- 1、前言随着技术的发展,微信的一系列服务渗透进了我们的生活,但是我们应该怎样进行微信方面的开发呢。相信很多的小伙伴们都很渴望知道吧。这篇文章
- 展示图: 对接的完整流程如下首先是配置gzh.appid=公众号appidwxPay.mchId=商户号wxPay.key=支付密
- C#2.0引入了泛型这个特性,由于泛型的引入,在一定程度上极大的增强了C#的生命力,可以完成C#1.0时需要编写复杂代码才可以完成的一些功能