(一)Spring源码解析:容器的基本实现

news2024/12/26 9:28:45

一、Spring的整体架构

Spring的整体架构图如下所示:

二、容器的基本实现

2.1> 核心类介绍

2.1.1> DefaultListableBeanFactory

DefaultListableBeanFactory是整个bean加载的核心部分,是Spring注册加载bean的默认实现。

XmlBeanFactory集成自DefaultListableBeanFactory,不同的地方是在XmlBeanFactory中使用了自定义的XML读取器XmlBeanDefinitionReader,实现了个性化的BeanDefinitionReader读取。源码部分如下图所示:

 DefaultListableBeanFactory类的继承关系如下图所示:

2.1.2> XmlBeanDefinitionReader

XML配置文件的读取是Spring中重要的功能,而XmlBeanDefinitionReader可以实现该功能。那么我们先来看一下这个类的继承关系:

  • ResourceLoader(接口:定义资源加载器,主要应用于根据给定的资源文件地址返回对应的Resource。
  • DocumentLoader(接口:定义从资源文件加载到转换为Document的功能。
  • BeanDefinitionDocumentReader(接口:定义读取Document并注册BeanDefinition功能。
  • BeanDefinitionParserDelegate(接口:定义解析Element的各种方法。
  • BeanDefinitionReader(接口:主要定义资源文件读取并转换为BeanDefinition的各个功能。
  • EnvironmentCapable(接口:定义获取Environment方法。
  • AbstractBeanDefinitionReader:对EnvironmentCapable、BeanDefinitionReader类定义的功能进行实现。

2.2> XmlBeanFactory的创建

如果想使用Spring,我们可以通过创建BeanFactory示例,然后调用getBean(...)来获得相应的实例对象,如下图所示:

  但是在获得BeanFactory的过程中,我们其实大体是经历了如下的几个步骤:

我们可以看到,第一步是获得了Resource。那么Resource是Spring用于封装底层资源,比如:FileURLClasspath等。对于不同来源的资源文件都有相应的Resource实现,比如:

针对文件资源:FileSystemResource
针对Classpath资源:ClassPathResource
针对URL资源:UrlResource
针对InputStream资源:InputStreamResource
针对Byte数组资源:ByteArrayResource
……

我们在日常开发工作中,如果需要对资源文件进行加载,也可以直接使用Spring提供的XxxResource类。比如,我们要加载oldbean.xml文件,则可以使用如下方式将其先转化为Resource ,然后再调用getInputStream() ,就可以或得到输入流了。那么针对于输入流的后续操作,与我们以往的处理方式是一样的。当然,除了能从Resource中获得InputStream之外,还可以获得FileURIURL等。具体请见下图所示:

 将Spring相关的配置文件封装为Resource类型实例之后,我们就可以继续创建XMLBeanFactory实例对象。如下是其构造函数源码:

2.3> loadBeanDefinitions(resource)加载bean

我们来看一个loadBeanDefinitions(...)方法的源码实现:

主要代码逻辑是用来根据xml配置文件的内容进行解析,然后使Spring加载bean。函数执行的时序图如下所示:

2.3.1> EncodedResource解析

我们发现resource又被EncodedResource类包装了一层。在构造EncodedResource实例的时候,我们可以指定resourceencodingcharset。具体源码如下图所示:

 那么当调用它的getReader()方法时,就会使用相应的字符集charset编码encoding作为输入流的charsetencoding

2.3.2> loadBeanDefinitions(EncodedResource encodedResource)

本方法就是针对EncodedResource实例对象进行bean的加载。具体执行如下3个步骤:

步骤1:将入参encodedResource保存到currentResources中,用于记录当前被加载的资源。如果发现已经存在了,则抛异常,终止资源加载。
步骤2:从encodedResource中获得输入流InputStream,并创建inputSource实例对象。如果在encodedResource中配置了编码(encoding),则为inputSource配置该编码。
步骤3:调用doLoadBeanDefinitions(...)方法从资源中加载bean。

具体源码实现逻辑,请见下图:

需要注意的一点是,InputSource不是Spring提供的类,它的全路径名是org.xml.sax.InputSource,用于通过SAX读取XML文件的方式来创建InputSource对象。

下面我们来看一下doLoadBeanDefinitions(...)方法的具体实现。在这个方法中,主要做了两件事件:

步骤1:加载XML配置文件,然后将其封装为Document实例对象。
步骤2:根据Document实例和Resource实例,执行Bean的注册。

 a> doLoadDocument(...)

doLoadDocument(...)方法中,我们需要关注下图中红框的两部分代码:

首先,我们来看一下getValidationModeForResource(Resource resource),具体源码逻辑如下图所示:

默认值为:VALIDATION_AUTO,如果发现现在的Mode不是VALIDATION_AUTO了,则说明有人自定义了,那么就返回自定义的Mode。如果没有被自定义,那么则通过detectValidationMode(resource)方法根据xml配置文件的格式,来确定Mode是DTD还是XSD

最后,我们来看一下detectValidationMode(resource)方法的具体实现,它到底是如何判断Mode的:

XML文件的验证模式保证了XML文件的正确性,而比较常用的有两种,即:DTD 和 XSD

DTDDocument Type Definition):它是一种XML约束模式语言,要使用DTD验证模式的时候需要在XML文件的头部声明****,并且它引用的是后缀名为.dtd的文件。如下所示:

XSDXML Schemas Definition):用于描述XML文档的结构。它引用的是后缀名为.xsd的文件。如下所示:

 看完getValidationModeForResource(resource)方法之后,我们再来看一下documentLoader.loadDocument(...)方法。为了便于理解,我们再次将相关代码粘贴出来:

loadDocument(...)方法是通过SAX解析XML文档,这段代码是套路性的代码,没什么好说的。就是创建DocumentBuilderFactory——>创建DocumentBuilder——>调用parse(inputSource)方法解析inputSource实例然后返回Document对象

 在上面黄框圈中的EntityResolver实例,它的作用是:DTD默认寻找规则是通过网络(即:声明的DTD的URI地址)来下载相应的DTD声明,并进行认证。由于网络原因,下载速度本身就是耗时的。那么,我们可以通过EntityResolver来实现寻找DTD声明的过程,比如:我们将DTD文件放到项目中的某个路径下,在实现时直接将此文档读取并返回给SAX即可。

黄框中的EntityResolver实例,它是一个接口,并且提供了一个resovleEntity(...)方法,源码如下所示:

那么publicIdsystemId是什么呢?如果是下图中的XSD的配置文件,那么publicId=nullsystemId=http://www.springframework.org/schema/beans/spring-beans.xsd

如果是下图中的DTD的配置文件,那么publicId=-//SPRING//DTD BEAN 2.0//ENsystemId=https://www.springframework.org/dtd/spring-beans-2.0.dtd

好了,了解了publicId和systemId之后,我们要将关注点放在对EntityResolver实例的获取过程了,在doLoadDocument(...)方法中,是通过 getEntityResolver()获得的,那我们就来看一下getEntityResolver()的具体实现:

既然最终都是要通过调用DelegatingEntityResolver的构造方法,我们就来看看它的内部实现:

BeansDtdResolver:是直接截取systemId最后的xx.dtd,然后去当前路径下寻找。
PluggableSchemaResolver:是默认到META-INF/spring.schemas文件中找到systemId所对应的XSD文件并加载。

b> registerBeanDefinitions(...)

在上面的内容中,我们已经将xml配置文件通过SAX解析成了Document实例对象了。那么下面,我们就要操作这个Document实例对象doc进行bean的注册操作了。在介绍具体操作细节之前,我们先看一下相关源码部分:

由于BeanDefinitionDocumentReader只是接口,所以通过createBeanDefinitionDocumentReader()方法其实创建的是它的实现类——DefaultBeanDefinitionDocumentReader。具体代码如下所示:

好了,看完了createBeanDefinitionDocumentReader()方法创建了DefaultBeanDefinitionDocumentReader实例之后,我们再继续看documentReader.registerBeanDefinitions(...)方法:

profile最主要的目的就是可以区分不同的环境,进而对不同环境进行配置。例如在devtestpreonlineonline等环境有各自的配置文件,我们就可以通过设置profile来在特定的环境下读取对应的配置文件。使用方式如下所示:

了解了profile之后,我们来看一下要执行xml解析的关键方法parseBeanDefinitions(root, this.delegate),它会根据表空间(如果命名空间等于"http://www.springframework.org/schema/beans",则表示是默认表空间,否则是自定义表空间)来判断,是进行默认标签解析还是自定义标签解析。相关源码如下所示:

默认标签<bean id="m416" class="com.muse.springbootdemo.entity.Gun">

自定义标签: <tx:annotation-driven>

对于默认标签来说,Spring自己就知道如何去解析;而对于自定义标签来说,就需要用户实现一些接口及配置了。那么关于这两种标签类型的解析,也就是我们后续关注的重点了。具体内容请见下一篇文章:默认标签解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/193444.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【FLASH存储器系列十四】固态硬盘结构和FTL初探

固态硬盘是一种典型的nand flash产品应用。与传统硬盘相化&#xff0c;固态硬盘内部没有移动的机械磁头&#xff0c;而是由固态电子存储芯片&#xff08;闪存芯片&#xff09;阵列级联组成&#xff0c;下图给出了固态硬盘的内部组成。现阶段&#xff0c;几乎所有基于闪存的固态…

ASP.NET Core+Element+SQL Server开发校园图书管理系统(三)

随着技术的进步&#xff0c;跨平台开发已经成为了标配&#xff0c;在此大背景下&#xff0c;ASP.NET Core也应运而生。本文主要基于ASP.NET CoreElementSql Server开发一个校园图书管理系统为例&#xff0c;简述基于MVC三层架构开发的常见知识点&#xff0c;前两篇文章简单介绍…

Nvidia深度学习环境安装

深度学习大型模型训练和部署&#xff0c;需要使用GPU&#xff0c;使用Pytorch、Tensorflow等深度学习框架之前需要安装驱动环境,本文系统环境&#xff1a;ubuntu22.04系统&#xff0c;四张3090显卡安装显卡驱动下载&#xff1a;选择显卡类型&#xff0c;下载驱动驱动下载路径&a…

Wireshark解析协议不匹配

Wireshark解析协议不匹配 1、问题 现有TLS/SSL over TCP的客户端、服务端相互通信&#xff0c;其中&#xff0c;服务端监听TCP端口6000。 使用tcpdump抓包6000端口&#xff0c;生成pcap文件6000.pcap&#xff1a; 使用Wireshark打开6000.pcap&#xff0c;显示如下&#xff1…

Hive(番外):Hive可视化工具IntelliJ IDEA

1 Hive CLI、Beeline CLI Hive自带的命令行客户端 优点&#xff1a;不需要额外安装 缺点&#xff1a;编写SQL环境恶劣&#xff0c;无有效提示&#xff0c;无语法高亮&#xff0c;误操作几率高 2 文本编辑器 Sublime、Emacs 、EditPlus、UltraEdit、Visual Studio Code等 有…

基于Seam Carving实现图像的重定位 附完整代码

相比于算法目标的复杂&#xff0c;算法步骤却异常的简单&#xff0c;下面具体介绍利用 SeamCarving 算法进行图像剪裁的步骤&#xff1a;1.计算图像中每个像素的“重要程度”&#xff08;能量&#xff09;&#xff0c;生成能量图。在绝大多数情况下&#xff0c;我们可以做出如下…

【string 类的使用方法(总结)】

1. 为什么学习string类&#xff1f; C语言中&#xff0c;字符串是以\0结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;C标准库中提供了一些str系列的库函数&#xff0c;但是这些库函数与字符串是分离开的&#xff0c;不太符合OOP的思想&#xff0c;而且底层空间需要…

采用NVIDIA Jetson Orin NX 系统的视觉边缘计算机

边缘计算机采用NVIDIA Jetson Orin NX模块化系统和高带宽图像采集卡&#xff0c;用于实时图像采集计算和人工智能处理。虹科的合作伙伴Gidel是一家专注于高速图像采集和处理的以色列科技公司&#xff0c;今天宣布新的NVIDIA Jetson Orin NX™ 16GB模块化系统(SoM)将被添加到Gid…

SpringSecurity配置及使用

Spring Security 是针对Spring项目的安全框架&#xff0c;也是Spring Boot底层安全模块默认的技术选型&#xff0c;他可以实现强大的Web安全控制&#xff0c;对于安全控制&#xff0c;我们仅需要引入spring-boot-starter-security 模块&#xff0c;进行少量的配置&#xff0c;即…

什么是渲染农场,渲染农场一般怎么收费?

对于用3D软件创作效果图或影视动画的艺术家们来说&#xff0c;应该对渲染农场并不陌生&#xff0c;但是对于初入CG行业的人来说&#xff0c;看到网上很多人说渲染农场&#xff0c;肯定会疑惑&#xff0c;什么是渲染农场&#xff1f;渲染农场也叫“分布式并行集群计算系统”&…

【6】【vue3+elementplus+springboot】 管理系统 【前后端实践】

第一部分&#xff1a; elementplus官网&#xff1a;一个 Vue 3 UI 框架 | Element Plus (element-plus.org) 1、安装elementplus npm install element-plus --save查看package.json中存在依赖表示成功安装 2、引入elementplus import ElementPlus from element-plus import …

论文解读 - 城市自动驾驶车辆运动规划与控制技术综述 (第5部分,完结篇)

文章目录&#x1f697; V. Vehicle Control&#xff08;车辆控制&#xff09;&#x1f534; A. Path Stabilization for the Kinematic Model&#xff08;基于运动学模型的路径稳定&#xff09;&#x1f7e5; 1&#xff09;Pure Pursuit&#xff08;纯追踪&#xff09;&#x1…

H3C SecParh堡垒机任意用户登录与远程执行代码漏洞

H3C SecParh堡垒机任意用户登录与远程执行代码漏洞1.H3C SecParh堡垒机任意用户登录漏洞1.1.漏洞描述1.2.漏洞影响1.3.漏洞复现1.3.1.登录页面1.3.2.构建URL1.4.总结2.H3C SecParh堡垒机远程命令执行漏洞2.1.漏洞描述2.2.漏洞影响2.3.漏洞复现2.3.1.登录页面2.3.2.构建URL2.4.总…

python-pptx 操作PPTx幻灯片文件删除并替换图片

python-pptx 操作PPTx幻灯片文件删除并替换图片 作者&#xff1a;虚坏叔叔 博客&#xff1a;https://xuhss.com 早餐店不会开到晚上&#xff0c;想吃的人早就来了&#xff01;&#x1f604; 一、原理 通过查找ppt中的图片指纹替换 二、操作流程 原始ppt如下&#xff1a; 根据…

[单片机] MCU串口发送C方案优化

应用场景&#xff1a; 主频不高非操作系统的单片机&#xff0c;需要在while循环中发送 数据到上位机&#xff0c;当数据较长时&#xff0c;会让发送的过程会让其他操作有卡顿感。为了解决这个问题&#xff0c;需采用一种方法&#xff1a;在每次大循环中只发一个字节数据&#x…

HTML5+CSS3(一)-全面详解(学习总结---从入门到深化)

目录 ​编辑 第一个前端程序 学习效果反馈 前端工具的选择与安装 前端常见开发者工具 浏览器 VSCode中文语言包安装&#xff1a; 学习效果反馈 VSCode开发者工具快捷键 VSCode常用快捷键列表 学习效果反馈 HTML5简介与基础骨架 HTML5的DOCTYPE声明 HTML5基本骨架 html…

Linux(CentOS Stream 9)安装MySQL8.0

mysql8下载链接 链接&#xff1a;https://pan.baidu.com/s/1yBCDbDYUmQWjcM1SdS7Xng 提取码&#xff1a;t37m 上传到服务器上并解压 cd /usr/localtar -xvf mysql-8.0.21-linux-glibc2.12-x86_64.tar.xz解压包重命名为mysql mv mysql-8.0.21-linux-glibc2.12-x86_64 /usr/l…

Linux部署RKNN-toolkit过程以及异常点记录(详细记录)

文章目录Linux部署RKNN-toolkit过程以及异常点记录1.在Linux中安装Miniconda1.1 使用服务器下载Miniconda1.2 安装conda1.3 激活刚安装完成的软件1.4参考博文2.创建并激活Miniconda新环境&#xff08;rknn&#xff09;2.1 创建conda环境&#xff08;命名为rknn&#xff09;2.2 …

做亚马逊、沃尔玛测评自养号大额、退款一定要解决的几个问题?

大家好我是测评龙哥&#xff0c;今天我跟大家说下做亚马逊、沃尔玛测评自养号、退款、lu货、项目需要用到的防关联、防封号环境的一些底层技术原理。这里讲的内容我相信很少有人能掌握&#xff0c;都是一些比较难的IT术技。 如果你现在准备开始做测评是在了解阶段还是已经在做…

SRM-询报价管理系统搭建指南

1、简介1.1、案例简介本文将介绍&#xff0c;如何搭建SRM-询报价管理。1.2、应用场景企业根据询价需求通知参与报价的供应商&#xff0c;所有供应商会收到通知后进行报价&#xff0c;自动生成了比价数据&#xff0c;企业可参考比价数据对供应商进行选择。2、设置方法2.1、表单搭…