Spring源码解析八

上一节,我们知道Spring对xml文件的校验有两种方式,分别是DTD和XSD。这两种校验方式都有对应的解析器来获取jar包中的声明文件的。
在这里插入图片描述

获取dtd的声明文件

我们先到BeansDtdResolver这个类,看下dtd的声明文件是如何获取
在这里插入图片描述
进入到BeansDtdResolver类中,就发现了一个resolverEntity的方法,很明显它就是解析并获取dtd文件的方法,调用该方法传入了两个参数publicId、systemId。
Spring在解析XML文件时,会从xml文件中获取到这两个参数的值,分别如下:
publicId:-//SPRING//DTD BEAN//EN
systemId:http://www.springframework.org/dtd/spring-beans.dtd

不知道大家有没有发现,在创建ClassPathResource时候,传入了getClass()方法,该方法表示传入了当前类,也就是BeansDtdResolver,这样的话ClassPathResource就会从classpath找BeansDtdResolver类相同包名的路径,寻找相应的spring-beans.dtd文件。
在这里插入图片描述

获取XSD声明文件

我们再到PluggableSchemaResolver类中,看下如何获取xsd的声明文件。
在这里插入图片描述
可以看到,在PluggableSchemaResolver 类中也有相同的resolveEntity方法,而且同样需要传入参数publicId和systemId。
在这里插入图片描述
publicId: null
systemId: http://www.springframework.org/schema/beans/spring-beans.xsd
通过对比发现,publicId这个参数的校验值只有DTD类型才有,参数systemId就是声明文件的下载地址。在PluggableSchemaResolver 类中的resolveEntity方法是通过调用getSchemaMappings() 方法之后,然后传入参数systemId,来获取资源路径。那这个getSchemaMappings()方法又有什么作用呢?我们跟进去看一下
在这里插入图片描述
在getSchemaMappings方法中,成员变量schemaMappings一开始为空。接下来是通过PropertiesLoaderUtils的loadAllProperties的方法,传入了两个参数 schemaMappingsLocation 、classloader。那这个schemaMappingsLocation 又是什么呢?如下图:
在这里插入图片描述
在PluggableSchemaResolver类的构造方法中,会给成员变量schemaMappingsLocation 赋值为META-INF/spring.schemas。也就是说PropertiesLoaderUtils的loadAllProperties就是加载spring.schemas文件中所有的值。那具体加载的是什么值呢?,我们到spring-beans项目中的META-INF目录中看一下:
在这里插入图片描述
看到这里我们算是明白了,原来spring.schemas文件中,存放的就是以systemId为key,XSD声明文件在项目中的包路径为value,所以我们可以通过systemId: http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
获取到value值:org/springframework/beans/factory/xml/spring-beans.xsd。
原来相比于DTD声明文件的获取方式,XSD声明文件的获取,还要根据具体的配置配置来寻找。
在这里插入图片描述
这个方法,会把spring.schemas中所有的值封装成一个Map然后返回,接下来我们可以通过参数systemId的值,获取xsd文件在项目中的路径,然后就可以获取到xsd声明文件了。
在这里插入图片描述
通过systemId从schemaMappings中获取resourceLocation,就是我们org/springframework/beans/factory/xml/spring-beans.xsd的值。也就是spring-beans.xsd声明文件在项目中的位置。接下来可以通过ClasspathResource,到classpath路径的resourceLocation位置加载资源。
在这里插入图片描述

如何获取XML的校验类型

DTD和XSD声明文件都是通过相应的EntityREsolver实现类来实现的。那spring是如何知道当前解析的xml文件,是DTD类型还是XSD类型呢?
我们回到之前的doLoadDocument方法。
在这里插入图片描述
我们到getValidationModeForResource方法中,看下xml文件的校验类型是如何判断的。
在这里插入图片描述
首先会通过getValidationMode方法获取的校验模式,默认的校验模式就是VALIDATION_AUTO,所以不会走第一个分支,我们看下detectValidationMode方法,看它是如何自动检测xml校验类型的:
在这里插入图片描述
可以看到,在detectValidationMode方法中,首先获取Resource资源的输入流,然后又委托给了XmlValidationModeDetector的detectValidationMode方法去检测了。我们继续进入XmlValidationModeDetector的detectValidationMode方法看下:
在这里插入图片描述
首先将输入流InputStream封装为一个可以缓冲的字符流,然后下面有个hasDocType方法来判断文件中是否包含“DOCTYPE” 。也就是说,如果检测到xml的内容中,包含“DOCTYPE” 字符串,就认定xml文件的校验方法为DTD,否则就是XSD。这样spring就可以根据具体的校验类型,分别使用不同的解析器去获取相应的校验文件。
下面总结下我们今天的内容:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

youngerone123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值