五陵年少金市东,银鞍白马渡春风。这篇文章主要讲述#yyds干货盘点#Spring源码三千问Spring AOP 中 TargetSource 的作用及原理分析相关的知识,希望能为你提供帮助。
@[TOC](Spring AOP 中 TargetSource 的作用及原理分析)
前言TargetSource
是 ProxyFactory
创建代理类时一个很重要的概念。
搞清楚 TargetSource 是什么,对我们理解 Spring AOP 有很大的帮助!
版本约定Spring 5.3.9 (通过 SpringBoot 2.5.3 间接引入的依赖)
正文TargetSource 的作用是用来获取 AOP 调用的当前“目标”(target)。
在调用 AOP 代理对象的方法时,在执行完所有的 advice chain 之后,最终会通过反射调用这个目标 target 的方法。
如果 TargetSource 是“静态”的,它将始终返回相同的目标 target,那么 Spring AOP 框架就可以对这种目标 Target 进行缓存,这样就不必每次都通过 TargetSource#getTarget()
来获取目标对象。
如果 TargetSource 是"
动态"
的,它也可以支持对象池(CommonsPool2TargetSource)、热交换(HotSwappableTargetSource)等功能。
应用程序开发人员通常不需要直接使用 TargetSource,这是一个 AOP 框架接口。
文章图片
普通的 AOP 代理创建使用的 TargetSourceSpring 中 99% 的 AOP 代理 bean 都会走
AutoProxyCreator#wrapIfNecessary()
来进行创建。它使用的 TargetSource 是
SingletonTargetSource
,也就是每次 SingletonTargetSource#getTarget()
都返回的是同一个对象。文章图片
@Async、@Valid 产生的代理使用的 TargetSource@Async、@Valid 标记的 bean 是使用
AbstractAdvisingBeanPostProcessor
来产生代理的。查看源码,可以发现这种情况最终也是使用的
SingletonTargetSource
。文章图片
@Lazy 产生的代理使用的 TargetSource@Lazy 使用在 @Resource/@Autowired 注入的属性上时,在依赖注入时,会注入一个代理对象,等真正调用代理 bean 的方法时,才会通过 TargetSource#getTarget() 来获取到真实的 bean 对象。
@Resource 属性上使用 @Lazy 时
可以看到,通过 ProxyFactory 创建代理时,使用的是 TargetSource 的匿名内部类。
每次调用
TargetSource#getTarget()
时,没有使用缓存,都会重新走一遍依赖注入的流程。文章图片
@Autowired 属性上使用 @Lazy 时
可以看到,通过 ProxyFactory 创建代理时,使用的是 TargetSource 的匿名内部类。
每次调用
TargetSource#getTarget()
时,没有使用缓存,都会重新走一遍依赖注入的流程。文章图片
TargetSource#isStatic()TargetSource 分为 “静态” 和 " 动态" 两类:
- Static TargetSource
它将始终返回相同的目标 target, Spring 会对这种 静态的TargetSource 进行优化,不必每次调用目标对象的方法都通过TargetSource#getTarget()
来获取目标对象。
- Dynamic TargetSource
对于 动态的TargetSource,每次调用目标对象的方法都需要通过TargetSource#getTarget()
来获取目标对象。
动态的TargetSource 在使用完之后,会调用TargetSource#releaseTarget()
来释放目标对象。
动态的TargetSource 可以支持对象池(CommonsPool2TargetSource)、热交换(HotSwappableTargetSource)等功能。
文章图片
jdk proxy 对 TargetSource#isStatic() 的处理
文章图片
小结TargetSource 是用来获取 AOP 调用的当前“目标对象”(target)的。
TargetSource 分为 “静态” 和 " 动态" 两类。
Spring 中绝大部分的场景都是使用的
SingletonTargetSource
,SingletonTargetSource 是静态TargetSource。@Lazy 使用的 TargetSource 是一个匿名内部类,它是 动态TargetSource,每次调用目标方法时都会调用 TargetSource#getTarget() 重新执行一遍依赖注入的流程,所以,会有一定的性能影响,不建议使用。可以考虑使用 ObjectProvider 进行代替,使用构造注入。
如果本文对你有所帮助,欢迎点赞收藏!
有关 Spring 源码方面的问题欢迎留言一起交流...
公众号后台回复:下载IoC 或者 下载AOP 可以免费下载源码测试工程…
【#yyds干货盘点#Spring源码三千问Spring AOP 中 TargetSource 的作用及原理分析】阅读更多文章,请关注公众号: 老王学源码
文章图片
博主好课推荐:
课程 | 地址 |
---|---|
Dubbo源码解读——通向高手之路 | https://edu.51cto.com/sd/2e565 |
正则表达式基础与提升 | https://edu.51cto.com/sd/59587 |
推荐阅读
- F5 GTM DNS 知识点和实验 5 -智能DNS的探针
- F5 GTM DNS 知识点和实验 6 -智能DNS算法
- 后台应用架构(单体SOA微服务)理解
- MySQL主从复制与读写分离解析和图文详细步骤
- 线程和进程有什么区别(转载)
- CentOS笔记
- Shell编程基础)
- F5 GTM DNS 知识点和实验 7 -同步组
- Python在Kivy中的RecycleView用法示例