EntityResolver
- Author: HuiFer
- 源码阅读仓库: huifer-spring
- 源码路径:
org.xml.sax.EntityResolver,非 Spring 类
DelegatingEntityResolver#resolveEntity
- org.springframework.beans.factory.xml.DelegatingEntityResolver.resolveEntity
@Override@Nullablepublic InputSource resolveEntity(@Nullable String publicId, @Nullable String systemId)throws SAXException, IOException {if (systemId != null) {if (systemId.endsWith(DTD_SUFFIX)) {return this.dtdResolver.resolveEntity(publicId, systemId);}else if (systemId.endsWith(XSD_SUFFIX)) {return this.schemaResolver.resolveEntity(publicId, systemId);}}// Fall back to the parser's default behavior.return null;}
- 上述这段代码是针对 xml 进行校验
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
- 如上所示以
.xsd结尾,应该执行return this.schemaResolver.resolveEntity(publicId, systemId);方法http://www.springframework.org/schema/beans/spring-beans.xsd org.springframework.beans.factory.xml.PluggableSchemaResolver.resolveEntity
PluggableSchemaResolver#resolveEntity
@Override@Nullablepublic InputSource resolveEntity(@Nullable String publicId, @Nullable String systemId) throws IOException {if (logger.isTraceEnabled()) {logger.trace("Trying to resolve XML entity with public id [" + publicId +"] and system id [" + systemId + "]");}if (systemId != null) {// 获取当前 systemId 对应的资源// spring-framework\spring-beans\src\main\resources\org\springframework\beans\factory\xml\spring-beans.xsdString resourceLocation = getSchemaMappings().get(systemId);if (resourceLocation == null && systemId.startsWith("https:")) {// Retrieve canonical http schema mapping even for https declarationresourceLocation = getSchemaMappings().get("http:" + systemId.substring(6));}if (resourceLocation != null) {// 加载 resourceLocation 转换成 ResourceResource resource = new ClassPathResource(resourceLocation, this.classLoader);try {// 读取InputSource source = new InputSource(resource.getInputStream());source.setPublicId(publicId);source.setSystemId(systemId);if (logger.isTraceEnabled()) {logger.trace("Found XML schema [" + systemId + "] in classpath: " + resourceLocation);}return source;}catch (FileNotFoundException ex) {if (logger.isDebugEnabled()) {logger.debug("Could not find XML schema [" + systemId + "]: " + resource, ex);}}}}// Fall back to the parser's default behavior.return null;}


得到本地路径,后续直接返回读取资源
BeansDtdResolver#resolveEntity
创建一个 Dtd 的约束文件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/dtd/spring-beans-2.0.dtd"></beans>
@Override@Nullablepublic InputSource resolveEntity(@Nullable String publicId, @Nullable String systemId) throws IOException {if (logger.isTraceEnabled()) {logger.trace("Trying to resolve XML entity with public ID [" + publicId +"] and system ID [" + systemId + "]");}if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {int lastPathSeparator = systemId.lastIndexOf('/');int dtdNameStart = systemId.indexOf(DTD_NAME, lastPathSeparator);if (dtdNameStart != -1) {// 获取静态变量组装成文件名称(spring-beans.dtd)String dtdFile = DTD_NAME + DTD_EXTENSION;if (logger.isTraceEnabled()) {logger.trace("Trying to locate [" + dtdFile + "] in Spring jar on classpath");}try {// 加载资源Resource resource = new ClassPathResource(dtdFile, getClass());InputSource source = new InputSource(resource.getInputStream());source.setPublicId(publicId);source.setSystemId(systemId);if (logger.isTraceEnabled()) {logger.trace("Found beans DTD [" + systemId + "] in classpath: " + dtdFile);}return source;}catch (FileNotFoundException ex) {if (logger.isDebugEnabled()) {logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in classpath", ex);}}}}// Fall back to the parser's default behavior.return null;}
- systemId
https://www.springframework.org/dtd/spring-beans-2.0.dtd

总结
- DelegatingEntityResolver#resolveEntity,是对 xml 文档的校验前置步骤,根据
dtd和xsd加载本地资源文件spring-framework\spring-beans\src\main\resources\org\springframework\beans\factory\xml\spring-beans.dtdspring-framework\spring-beans\src\main\resources\org\springframework\beans\factory\xml\spring-beans.xsd PluggableSchemaResolver负责加载xsd文件BeansDtdResolver负责加载dtd文件
