4.Spring Context 装载过程源码分析
Spring的ApplicationContext是Spring框架中的核心接口之一,它扩展了BeanFactory接口,提供了更多的高级特性,如事件发布、国际化支持、资源访问等。ApplicationContext的装载过程是Spring框架中非常重要的一个环节。以下是ApplicationContext装载过程的源码分析:
1. 创建ApplicationContext实例
装载过程的第一步是创建一个ApplicationContext的实例。这通常通过调用ClassPathXmlApplicationContext、FileSystemXmlApplicationContext或AnnotationConfigApplicationContext等具体实现类的构造函数来完成。
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
2. 初始化BeanFactory
在ApplicationContext的实现类中,装载过程首先会初始化一个DefaultListableBeanFactory实例,这是BeanFactory的一个具体实现。
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
3. 设置BeanFactory属性
接着,ApplicationContext会设置BeanFactory的一些属性,如类加载器、Bean表达式解析器等。
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory));
4. 注册BeanPostProcessors
ApplicationContext会注册所有的BeanPostProcessor实现类。这些处理器会在Bean的初始化前后被调用。
beanFactory.addBeanPostProcessor(new MyBeanPostProcessor());
5. 装载Bean定义
根据ApplicationContext的具体实现,它会从不同的源装载Bean定义。例如,ClassPathXmlApplicationContext会从类路径下的XML文件中装载Bean定义。
loadBeanDefinitions(beanFactory);
6. 初始化MessageSource
如果需要,ApplicationContext会初始化一个MessageSource用于国际化。
initMessageSource();
7. 初始化应用事件多播器
ApplicationContext会初始化一个应用事件多播器,用于事件发布和监听。
initApplicationEventMulticaster();
8. 注册事件监听器
注册所有的事件监听器。
registerEventListeners();
9. 初始化其他基础设施
初始化其他Spring框架的基础设施,如ResourcePatternResolver等。
10. 调用BeanFactory的preInstantiateSingletons方法
这个方法会触发所有剩余的非懒加载的单例Bean的初始化。
beanFactory.preInstantiateSingletons();
11. 调用refresh()方法
最后,ApplicationContext会调用自身的refresh()方法来完成装载过程。这个方法会执行上述所有步骤,并确保容器完全初始化和就绪。
public void refresh() throws BeansException, IllegalStateException {
// …
}
refresh()方法是装载过程的核心,它协调了容器的初始化和Bean的创建。通过分析refresh()方法的源码,我们可以深入理解Spring容器是如何工作的。
请注意,上述步骤可能会根据不同的ApplicationContext实现类和配置有所变化。此外,Spring框架的版本更新也可能带来一些实现上的变化。上述分析基于Spring框架的一般装载过程。
BeanFactoryPostProcessor源码分析
BeanFactoryPostProcessor是Spring框架中的一个重要接口,它允许开发者在容器实例化和属性赋值完成后,初始化Bean之前,执行一些自定义逻辑。BeanFactoryPostProcessor接口定义了一个方法:
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
源码分析
在Spring容器初始化过程中,BeanFactoryPostProcessor的逻辑主要在AbstractApplicationContext类中实现。以下是源码分析的关键点:
注册BeanFactoryPostProcessor: 在容器初始化时,所有的BeanFactoryPostProcessor实现类都会被注册到容器中。
调用postProcessBeanFactory: 在BeanFactory的标准初始化之后,容器会调用所有注册的BeanFactoryPostProcessor的postProcessBeanFactory方法。这个方法允许开发者查看和修改BeanFactory中的Bean定义。
修改Bean定义: 在postProcessBeanFactory方法中,开发者可以添加新的Bean定义、修改现有Bean定义、或者删除某些Bean定义。
应用顺序: BeanFactoryPostProcessor的实现类可以定义它们的应用顺序。如果需要,可以通过实现Ordered接口或使用@Order注解来指定顺序。
调用时机: BeanFactoryPostProcessor的调用发生在Bean的属性赋值之后,初始化之前。这意味着,此时Bean的属性已经设置完成,但Bean还没有被初始化。
异常处理: 如果在BeanFactoryPostProcessor的调用过程中抛出了异常,容器会捕捉这个异常,并传播出去。
与BeanPostProcessor的区别: BeanFactoryPostProcessor作用于BeanFactory,而BeanPostProcessor作用于具体的Bean。BeanFactoryPostProcessor可以在Bean初始化之前对BeanFactory进行修改,而BeanPostProcessor可以在Bean的初始化过程中插入自定义逻辑。
示例
下面是一个简单的BeanFactoryPostProcessor实现示例,它在BeanFactory初始化后打印所有Bean定义的名称:
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {String[] beanNames = beanFactory.getBeanDefinitionNames();System.out.println("Bean names after BeanFactoryPostProcessor: ");for (String beanName : beanNames) {System.out.println(beanName);}
}
}
通过实现BeanFactoryPostProcessor接口,开发者可以在Spring容器初始化Bean之前,对BeanFactory进行自定义操作,这为实现一些高级特性提供了可能,例如自动装配、Bean定义的动态修改等。
BeanDefinitionRegistryPostProcessor源码分析
BeanDefinitionRegistryPostProcessor 是 Spring 框架中的一个接口,它扩展了 BeanFactoryPostProcessor 接口。与 BeanFactoryPostProcessor 相比,BeanDefinitionRegistryPostProcessor 提供了对 BeanDefinitionRegistry 的访问,允许在 post-processing 阶段注册新的 BeanDefinition。这使得开发者可以在容器的 BeanDefinition 加载完成之后、实例化 Bean 之前,动态地添加或修改 BeanDefinition。
以下是 BeanDefinitionRegistryPostProcessor 接口的定义:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/*** 在 BeanFactoryPostProcessor 的 postProcessBeanFactory 调用之后调用。* 允许在 BeanDefinitionRegistry 中注册更多的BeanDefinition。* @param registry BeanDefinitionRegistry 的实例* @throws org.springframework.beans.BeansException*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
源码分析
扩展 BeanFactoryPostProcessor:BeanDefinitionRegistryPostProcessor 接口继承自 BeanFactoryPostProcessor,因此它拥有 postProcessBeanFactory 方法的能力,并且可以访问 ConfigurableListableBeanFactory。
postProcessBeanDefinitionRegistry 方法:这是 BeanDefinitionRegistryPostProcessor 的核心方法,它允许开发者在 BeanDefinitionRegistry 中注册新的 BeanDefinition 或修改现有的 BeanDefinition。
调用时机:postProcessBeanDefinitionRegistry 方法在 postProcessBeanFactory 方法之后调用,确保开发者在注册新的 BeanDefinition 时,已有的 BeanDefinition 已经加载完成。
BeanDefinitionRegistry:BeanDefinitionRegistry 是一个接口,它定义了注册、移除和获取 BeanDefinition 的方法。postProcessBeanDefinitionRegistry 方法提供了对 BeanDefinitionRegistry 的访问,使得开发者可以操作 BeanDefinition。
BeanDefinition 的动态注册:开发者可以在 postProcessBeanDefinitionRegistry 方法中使用 BeanDefinitionRegistry 的 registerBeanDefinition 方法来注册新的 BeanDefinition。
BeanDefinition 的修改:除了注册新的 BeanDefinition,开发者还可以修改现有的 BeanDefinition,例如更改 Bean 的作用域、添加属性等。
异常处理:如果在 postProcessBeanDefinitionRegistry 方法中抛出异常,容器会捕捉这个异常并传播出去,这可能会中断 Bean 的创建过程。
示例
下面是一个简单的 BeanDefinitionRegistryPostProcessor 实现示例,它在 BeanDefinitionRegistry 中注册一个新的 BeanDefinition:
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// 可以在这里访问和修改 beanFactory
}@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {// 注册一个新的 BeanDefinitionRootBeanDefinition beanDefinition = new RootBeanDefinition(MyBean.class);registry.registerBeanDefinition("myBean", beanDefinition);
}
}
通过实现 BeanDefinitionRegistryPostProcessor 接口,开发者可以在 Spring 容器的 BeanDefinition 加载完成后,动态地注册或修改 BeanDefinition,这为实现一些复杂的配置和自定义行为提供了强大的支持。
相关文章:
4.Spring Context 装载过程源码分析
Spring的ApplicationContext是Spring框架中的核心接口之一,它扩展了BeanFactory接口,提供了更多的高级特性,如事件发布、国际化支持、资源访问等。ApplicationContext的装载过程是Spring框架中非常重要的一个环节。以下是ApplicationContext装…...
mysql之数据存储单元
简介 在MySQL中,单行数据存储单元的大小并不是固定的,它取决于多种因素,如表结构中使用的数据类型以及所使用的存储引擎。 但是我们可以提供一些关于MySQL中典型行数据存储单元大小的一般性指引: 存储引擎 InnoDB(默认存储引擎) InnoDB中单行数据存储单元的大小通常在8-16…...
未来20年人工智能将如何塑造社会
照片由Brian McGowan在Unsplash上拍摄 更多资讯,请访问 2img.ai “人工智能会成为我们的救星还是我们的末日?” 几十年来,这个问题一直困扰着哲学家、科学家和科幻爱好者。 当我们踏上技术革命的边缘时,是时候透过水晶球&#x…...
Maven的依赖传递、依赖管理、依赖作用域
在Maven项目中通常会引入大量依赖,但依赖管理不当,会造成版本混乱冲突或者目标包臃肿。因此,我们以SpringBoot为例,从三方面探索依赖的使用规则。 1、 依赖传递 依赖是会传递的,依赖的依赖也会连带引入。例如在项目中…...
ArcGIS定义1.5度带坐标系与投影转换
点击下方全系列课程学习 点击学习—>ArcGIS全系列实战视频教程——9个单一课程组合系列直播回放 点击学习——>遥感影像综合处理4大遥感软件ArcGISENVIErdaseCognition 对于ArcGIS如何定义高斯克吕格3度带、6度带,我相信大部分人都是比较清楚的࿰…...
艺术与科技的精湛融合:探讨AI绘画与AI动画的交汇点
前言 艺术与科技的精湛融合:探讨AI绘画与AI动画的交汇点 在当代社会中,艺术和科技的结合呈现出了从来灭有的创新和可能性。随着人工智能技术的不断发展,AI绘画与AI动画的融合愈发引人瞩目。这一融合不仅给艺术家们带来了更多创作的可能&…...
【移动应用开发期末复习】第五/六章
系列文章 第一章——Android平台概述 第一章例题 第二章——Android开发环境 第二章例题 第三章 第三章例题 第四章 系列文章界面布局设计线性布局表格布局帧布局相对布局约束布局控制视图界面的其他方法代码控制视图界面数据存储与共享首选项信息数据文件SQLite数据库Content…...
excel FORMULA
在Excel中,FORMULA 实际上是一个拼写错误。您可能是指 FORMULA 的正确拼写 FORMULA(这在Excel中不是有效的函数或关键字),但更可能是您想要讨论的是FORMULA(公式)的创建或使用。 在Excel中,您可…...
【学习】开发板接口
工作用到机器的开发板 有如上三个接口 。最右是仿真器,中间是RS232串口,最左是电源线 仿真器 这个是仿真器 接入机器那端用的是SWD模式,另一端通过USB接电脑(这小肥手拍的怪好看)仿真口连接了四条线分别是 VCC&#…...
主干网络篇 | YOLOv5/v7 更换骨干网络之 EfficientNet | 卷积神经网络模型缩放的再思考
主干网络篇 | YOLOv5/v7 更换骨干网络之 EfficientNet | 卷积神经网络模型缩放的再思考 1. 简介 近年来,深度卷积神经网络(CNN)在图像识别、目标检测等领域取得了巨大进展。然而,随着模型复杂度的不断提升,模型训练和…...
如何测试Java应用的性能?
如何测试Java应用的性能? 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 在开发Java应用程序的过程中,性能测试是一个不可忽视的重要环…...
css 动画
当涉及到CSS动画时,有几种方式可以实现动画效果。以下是一些常见的CSS动画技术: 使用keyframes规则:keyframes规则允许你创建一个动画序列,定义动画的关键帧和属性值。例如,你可以创建一个旋转动画,让一个…...
# 设置 Linux 安全策略允许本地 IP 开通了访问权限
设置 Linux 安全策略允许本地 IP 开通了访问权限 在 Linux 中设置安全策略通常涉及使用 iptables 或者 firewalld( 在较新的 Red Hat/CentOS 版本中)。以下是使用 iptables 允许特定本地 IP 访问的例子: 1、先清除现有的规则(谨…...
C++初学者指南第一步---14.函数调用机制
C初学者指南第一步—14.函数调用机制 文章目录 C初学者指南第一步---14.函数调用机制1.记住:内存的结构2.函数调用是如何工作的3. 不要引用局部变量4. 常见编译器优化5. Inlining内联 1.记住:内存的结构 堆(自由存储) 用于动态存…...
Apache Flink类型及序列化研读生产应用|得物技术
一、背景 序列化是指将数据从内存中的对象序列化为字节流,以便在网络中传输或持久化存储。序列化在Apache Flink中非常重要,因为它涉及到数据传输和状态管理等关键部分。Apache Flink以其独特的方式来处理数据类型以及序列化,这种方式包括它…...
如何使用代理 IP 防止多个 Facebook 帐户关联 - 最佳实践
在社交媒体被广泛应用的今天,Facebook作为全球最大的社交网络平台之一,面临着很多挑战,其中之一就是用户行为的管理和安全。 为了防止多个账户之间的关联和滥用,Facebook需要采取一系列措施,其中包括使用静态住宅代理…...
DDei在线设计器-API-DDeiAbstractShape
DDeiAbstractShape DDeiAbstractShape代表是所有可见图形的父类,定义了图形所需要的公共属性和方法。 DDeiAbstractShape实例包含了一个图形的所有数据和渲染器,在获取后可以通过它访问其他内容。DDeiAbstractShape中的layer指向所在图层,stage指向所…...
IPython的使用技巧整理
关于IPython的使用技巧有很多,这里只是梳理了几个常用的以及我目前遇到过的,其他的技巧还没使用过,所以就没有列出来。 01|Tab键自动完成:在shell中输入表达式时,只要按下Tab键,当前命名空间中任何与已输入的字符串相…...
vue项目纯前端实现导出pdf文件
1、下载插件 npm install html2canvas npm install jspdf2、创建htmlToPdf.js,地址:src/utils/htmlToPdf.js import html2Canvas from html2Canvas import JsPDF from jspdf export default { install(Vue, options) { Vue.prototype.getPdfFromH…...
以Bert训练为例,测试torch不同的运行方式,并用torch.profile+HolisticTraceAnalysis分析性能瓶颈
以Bert训练为例,测试torch不同的运行方式,并用torch.profileHolisticTraceAnalysis分析性能瓶颈 1.参考链接:2.性能对比3.相关依赖或命令4.测试代码5.HolisticTraceAnalysis代码6.可视化A.优化前B.优化后 以Bert训练为例,测试torch不同的运行方式,并用torch.profileHolisticTra…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...
