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
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Android 进程间通信实现原理分析
![](https://img.aspxhome.com/file/2023/3/122223_0s.gif)
C#使用读写锁三行代码简单解决多线程并发的问题
![](https://img.aspxhome.com/file/2023/5/96335_0s.png)
基于WPF实现绘制地铁路线图
![](https://img.aspxhome.com/file/2023/0/125900_0s.jpg)
Java Swing中JTable渲染器与编辑器用法示例
![](https://img.aspxhome.com/file/2023/1/68181_0s.jpg)
AnyChat的视频会议程序实例详解
![](https://img.aspxhome.com/file/2023/8/89868_0s.png)
详解Java 自动装箱与拆箱的实现原理
使用纯Java实现一个WebSSH项目的示例代码
![](https://img.aspxhome.com/file/2023/8/64148_0s.png)
JDK1.8中ArrayList是如何扩容的
![](https://img.aspxhome.com/file/2023/0/62700_0s.png)
使用PageHelper插件实现Service层分页
![](https://img.aspxhome.com/file/2023/2/65272_0s.jpg)
Java动态代理模式的深入揭秘
![](https://img.aspxhome.com/file/2023/9/113249_0s.jpg)
Java利用MessageFormat实现短信模板的匹配
SpringMVC如何获取表单数据(radio和checkbox)
![](https://img.aspxhome.com/file/2023/5/83155_0s.png)
java多线程编程之join方法的使用示例
springboot自动配置原理以及spring.factories文件的作用详解
![](https://img.aspxhome.com/file/2023/6/89586_0s.png)
Spring Boot提高开发效率必备工具lombok使用
![](https://img.aspxhome.com/file/2023/7/110907_0s.png)