当前位置: 首页 > news >正文

Spring IOC 源码学习 事务增强相关的对象创建

事务增强相关的对象创建

internalAutoProxyCreator 对象

首先是 internalAutoProxyCreator 它是负责创建AOP对象 它本身是BPP, 它会在 registerBeanPostProcessors(beanFactory); 过程中被实例化
org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, org.springframework.context.support.AbstractApplicationContext)

/***  in short:*  1. 拿到所有实现 BeanPostProcessor 的 bean, 然后进行分类存起来*  这有一点, Spring 对 BeanDefinition 分成三种角色:*  	1. 用户定义的 Bean (ROLE_APPLICATION)*      2. 较复杂的 (ROLE_SUPPORT) 较复杂的? 通常是一个外部配置*      3. Spring 内置的(ROLE_INFRASTRUCTURE)*  2. 如果实现了 BeanPostProcessor 则会实例化这个bean, 但注意这里只是注册,并不会调用BeanPostProcessor的相关方法**  另外 BeanPostProcessor 粗粒度太大, Spring 还细分一些子接口:*  - SmartInstantiationAwareBeanPostProcessor 它提供了更高级的Bean实例化控制方法。主要作用在于允许对Bean的实例化过程进行更精细的控制和定制。*  - MergedBeanDefinitionPostProcessor 在合并Bean定义(MergedBeanDefinition)之后但在实例化Bean之前,允许对合并后的Bean定义进行修改、调整或附加元数据。*  - DestructionAwareBeanPostProcessor 它允许在Bean被销毁之前(例如,容器关闭或特定作用域的Bean销毁)执行一些操作。*/public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {// WARNING: Although it may appear that the body of this method can be easily// refactored to avoid the use of multiple loops and multiple lists, the use// of multiple lists and multiple passes over the names of processors is// intentional. We must ensure that we honor the contracts for PriorityOrdered// and Ordered processors. Specifically, we must NOT cause processors to be// instantiated (via getBean() invocations) or registered in the ApplicationContext// in the wrong order.//// Before submitting a pull request (PR) to change this method, please review the// list of all declined PRs involving changes to PostProcessorRegistrationDelegate// to ensure that your proposal does not result in a breaking change:// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22/*** 拿到所有实现 BeanPostProcessor 的 bean名称*/String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);// Register BeanPostProcessorChecker that logs an info message when// a bean is created during BeanPostProcessor instantiation, i.e. when// a bean is not eligible for getting processed by all BeanPostProcessors./*** 计算 BeanPostProcessor(BPP) 的总数.* +1 是什么操作? 原因是: 下一行,又加了一个 BeanPostProcessorChecker*/int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;// BeanPostProcessorChecker 这个BeanPostProcessor, 没啥实际作用, 就是记录了一些日志;beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, postProcessorNames, beanProcessorTargetCount));// Separate between BeanPostProcessors that implement PriorityOrdered,// Ordered, and the rest./*** 对 BeanPostProcessor 进行分类存起来,  再调用, 每个集合分别是* 1. priorityOrderedPostProcessors //有实现(PriorityOrdered)排序接口的* 2. internalPostProcessors //Spring内部的bean, 见: Spring将bean分为三种角色* 3. orderedPostProcessorNames //实现 Ordered 接口* 4. nonOrderedPostProcessorNames //没有指定顺序, 无序的*/List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();List<String> orderedPostProcessorNames = new ArrayList<>();List<String> nonOrderedPostProcessorNames = new ArrayList<>();for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {/*** 注意, 若 bean 实现了 PriorityOrdered 接口, 则会优先实例化它;*/BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);priorityOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {nonOrderedPostProcessorNames.add(ppName);}}// First, register the BeanPostProcessors that implement PriorityOrdered.sortPostProcessors(priorityOrderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);// Next, register the BeanPostProcessors that implement Ordered.List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());for (String ppName : orderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);orderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}sortPostProcessors(orderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, orderedPostProcessors);/*** 注册所有常规BeanPostProcessors* 这里 getBean 实例化bean !;*/// Now, register all regular(常规) BeanPostProcessors.List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());for (String ppName : nonOrderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);nonOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);/*** 最后, 注册所有 内置 BeanPostProcessor*/// Finally, re-register all internal BeanPostProcessors.sortPostProcessors(internalPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, internalPostProcessors);//最后再放一个 ApplicationListenerDetector 让它在最后 (不是重点, 见名应该是事件相关的)// Re-register post-processor for detecting inner beans as ApplicationListeners,// moving it to the end of the processor chain (for picking up proxies etc).beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));}

DefaultBeanFactoryPointcutAdvisor 和 AspectJExpressionPointcut 对象

internalAutoProxyCreator 会在 postProcessBeforeInstantiation 回调中的org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#shouldSkip判断时实例化所有的 Advisor

在实例化 Advisor 填充属性时也会把 AspectJExpressionPointcut 也实例化

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation

@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {/*** 常规情况下:  这里只是检查下缓存和标记缓存* 对于真正的AOP代理创建见:* {@link AbstractAutoProxyCreator#postProcessAfterInitialization(java.lang.Object, java.lang.String)}*/Object cacheKey = getCacheKey(beanClass, beanName);if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {/****  不管需不需要, 只要处理过了就缓存* 	advisedBeans 这个变量, 缓存所有处理过的 bean名称;* 	value 为 boolean值, 如果为false 则不处理*/if (this.advisedBeans.containsKey(cacheKey)) {return null;}/*** isInfrastructureClass 是否是基础功能类,即 AOP相关的几个类:* Advice.class Pointcut.class Advisor.class AopInfrastructureBean.class 都为true** shouldSkip 判断时, 拿到容器的所有 Advisor, 并且实例化 `getBean()` 这个 Advisor*/if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return null;}}// Create proxy here if we have a custom TargetSource.// Suppresses unnecessary default instantiation of the target bean:// The TargetSource will handle target instances in a custom fashion.TargetSource targetSource = getCustomTargetSource(beanClass, beanName);if (targetSource != null) {if (StringUtils.hasLength(beanName)) {this.targetSourcedBeans.add(beanName);}Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}return null;}

TransactionInterceptort 对象

是在 internalAutoProxyCreator 遇到需要增强代理的对象时, 这里是 bookService 去 getAdvicesAndAdvisorsForBean 查找到其匹配 bookService 的 Advisor
这里若 Advisor 匹配, 会调用 getAdvice 获取其切面, 此时切面不存在则会实例化它

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}/*** 拿到所有匹配织入当前bean的 所有通知器(Advisor)* 做了三件事, 见: {@link org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean(java.lang.Class, java.lang.String, org.springframework.aop.TargetSource)}* 1. 往返回 `AspectJXXXAdvice`列表数组`0`索引 插入一个{@link org.springframework.aop.interceptor.ExposeInvocationInterceptor} 实例* 方便传递参数用的** 2. 怎么匹配(Advisor)?* Advisor中的 `AspectJExpressionPointcut` 是实现 {@link ClassFilter} 和 {@link org.springframework.aop.MethodMatcher} 接口* 一个进行类匹配, 一个进行方法匹配. Advisor 匹配会调用 getAdvice 获取其切面, 此时切面不存在则会实例化** 3.  排序, 基于 `有向无环` 图进行排序; 可能匹配到多个切面(aspect)**/// Create proxy if we have advice.Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {/***{@link org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#advisedBeans}* 这个变量缓存所有处理过的 bean名称, value 为 boolean值, 如果为false 则不处理*/this.advisedBeans.put(cacheKey, Boolean.TRUE);//缓存, 表示已处理/*** 创建代理**/Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}

汇总图

Spring TX

http://www.jsqmd.com/news/519514/

相关文章:

  • 2026年03月21日最热门的开源项目(Github)
  • 避坑指南:C# NumericUpDown控件5个常见错误用法及正确姿势
  • Uniapp实战:5分钟搞定谷歌地图选点定位(附完整代码与避坑指南)
  • STLink维修避坑指南:为什么你的固件刷写总失败?从写保护解除到芯片选型详解
  • 2026-03-22 全国各地响应最快的 BT Tracker 服务器(联通版)
  • python cosyVoice实现tts文本转语音、音频(未完成)
  • 别再死记硬背了!用Keil5和STM32F103C8T6搞懂GPIO八种模式,看这篇就够了
  • QCLAW 浏览器联通指南:原理、架构与配置详解
  • 大容量硬盘空间管理实战:用EternalBlaze硬链接技术优化TB级存储资源
  • LabVIEW打造轻量级无人机GCS地面站:从地平仪到电子地图的全流程解析
  • 从杜邦分析到RFM模型:手把手教你用Excel实现7大商业分析框架
  • 从YouTube到国内大厂,VPU(视频处理单元)如何重塑视频云的技术栈?
  • 重复文件处理的三种方案对比:删除、压缩还是硬链接?EternalBlaze实测报告
  • 深搜算法 6300:Grid Path Construction(2418)
  • 从吾爱论坛到开源神器:EternalBlaze作者的技术初心与硬链接工具诞生记
  • Java面上 HashMap Put方法 扩容机制 实现
  • Ubuntu22.04网络图标消失?5分钟快速修复指南(附详细命令)
  • 3DTiles白膜性能优化指南:如何让SHP建筑模型在Cesium中流畅加载
  • 【嵌入式性能生死线】:C语言驱动CAN FD控制器的7步原子操作加固法(ST/Infineon/NXP全平台验证)
  • 【国产单片机】华大HC32L13系列printf调试实战:从半主机模式到MicroLib的深度解析
  • OpenHarmony开发避坑指南:手把手教你写对BUILD.gn,解决90%的编译问题
  • 利用Mermaid在Markdown中高效构建数据库ER图
  • 别再乱用jet了!Matplotlib中5个最值得推荐的科学可视化colormap及使用场景
  • 2025美赛B题实战复盘:从零构建可持续旅游模型,Python代码全解析
  • FreeDOS 技术揭秘:从开源内核到经典DOS应用的全栈解析
  • ESP32驱动OV7670摄像头(无FIFO)保姆级教程:从GitHub克隆到网页实时显示
  • 华为Eth-Trunk链路聚合实战:从原理到配置详解
  • 锂离子电池恒流恒压充电Simulink仿真模型(CC-CV)及其电路结构与充电过程说明
  • nnUNetV2实战:从零构建医学影像2D分割数据集全流程解析
  • AI代写泛滥后,我实测5款论文降AI神器,帮我从80%拉到2%