我是靠谱客的博主 平常大白,最近开发中收集的这篇文章主要介绍spring源码(1)从xml到org.w3c.dom.Document一、XmlBeanFactory的构造函数二、XmlBeanDefinitionReader读取XML,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

从以下这一小段代码说起:

new XmlBeanFactory(new ClassPathResource("springContext.xml"));

这小段看似简单仅仅实例化了两个对象,但是这只是表象。

一、XmlBeanFactory的构造函数

查看代码发现XmlBeanFactory有两个构造函数:

private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}

最终会执行的代码是:

//执行父类带参构造函数
super(parentBeanFactory);
//执行XmlBeanDefinitionReader的loadBeanDefinitions
this.reader.loadBeanDefinitions(resource);

可以看到this.reader.loadBeanDefinitions才是资源加载的真正实现。XmlBeanFactory相当于 DefaultListableBeanFactory + XmlBeanDefinitionReader,既可以对bean进行一些操作,又可以读取XML。

Resource用来封装配置文件。

二、XmlBeanDefinitionReader读取XML

一路走下去,方法到了doLoadBeanDefinitions方法,开始解析XML文件的地方(做了些简化):

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
...
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
...
}

进入doLoadDocument(inputSource, resource),实际上是使用配置的documentLoader来解析XML的:

protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}

常见的XML解析方式有:DOM、SAX、dom4j等,那么spring中使用的是哪种方式呢?
spring中采用的是DOM方式,所要做的一切就是得到org.w3c.dom.Document。
loadDocment 传递的参数有:
① EntityResolver : 指定XML验证方式,实现先从本地获取XSD或者DTD文件
② errorHandler : 解析错误处理类
③ ValidationMode : 验证方式XSD、DTD
④ isNamespaceAware :是否支持命名空间

EntityResolver、errorHandler参考:http://blog.csdn.net/disiwei1012/article/details/75209030

一、验证模式介绍

ValidationMode:比较常用的验证方式有两种:DTD和XSD

DTD模式:
要使用DTD进行验证,需要在XML文件的头部声明,同时需要制定DTD文件的位置。
spring中使用DTD如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">

XML的DOCTYPE有两个属性publicId和systemId,这两个东西都可以用来制定DTD文件的位置。所不同的是systemId指定的是具体的资源文件,它可以是相对路径也可以是绝对路径,而publicId则是使用定义的名称查找资源文件

publicId 是一个公共资源的知名标识,解析器可以根据这个名字得到一个资源(一般是DTD),如果根据这个名字没能找到一个资源,那么会根据systemId(一般是一个URL)来获取这个资源,如果还获取不到,那么会报错。也就是说,publicId和systemId是一个网络资源的标识,前者标识名字,后者标识URL,一般是成对出现。

解析器获取publicId标识的资源,一般是通过网络下载,这会导致解析速度变慢,或者解析失败。因此,可以在解析前编写验证文件,或者制定验证文件的地址。

上面的:
publicId:-//SPRING//DTD BEAN 2.0//EN
systemId:http://www.springframework.org/dtd/spring-beans-2.0.dtd

XSD模式:
使用XSD验证,除了声明命名空间外xmlns,还要通过schemaLocation来指定该命名空间验证文件的位置。

<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
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans> -->

publicId:null
systemId:http://www.springframework.org/schema/beans/spring-beans.xsd

二、spring中对xml的验证

接着往下走:

public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
if (logger.isDebugEnabled()) {
logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
}
DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
return builder.parse(inputSource);
}

和咱们想象的差不多,先创建DocumentBuilderFactory,然后DocumentBuilder,然后parse。

protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware)
throws ParserConfigurationException {
//创建DocumentBuilderFactory
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//是否支持命名空间
factory.setNamespaceAware(namespaceAware);
//如果需要进行xml验证,而且是XSD验证,强制支持命名空间
if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
factory.setValidating(true);
if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
// Enforce namespace aware for XSD...
factory.setNamespaceAware(true);
try {
factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
}
catch (IllegalArgumentException ex) {
ParserConfigurationException pcex = new ParserConfigurationException(
"Unable to validate using XSD: Your JAXP provider [" + factory +
"] does not support XML Schema. Are you running on Java 1.4 with Apache Crimson? " +
"Upgrade to Apache Xerces (or Java 1.5) for full XSD support.");
pcex.initCause(ex);
throw pcex;
}
}
}
return factory;
}
//没啥需要解释的
protected DocumentBuilder createDocumentBuilder(
DocumentBuilderFactory factory, EntityResolver entityResolver, ErrorHandler errorHandler)
throws ParserConfigurationException {
DocumentBuilder docBuilder = factory.newDocumentBuilder();
if (entityResolver != null) {
docBuilder.setEntityResolver(entityResolver);
}
if (errorHandler != null) {
docBuilder.setErrorHandler(errorHandler);
}
return docBuilder;
}

三、另外看下spring的entityResolver

如果没有特备指定entityResolver,则使用默认的entityResolver。
getResourceLoader是XmlBeanDefinitionReader父类AbstractBeanDefinitionReader中的方法,查看后发现resourceLoader == null。
所以真正使用的是DelegatingEntityResolver。

protected EntityResolver getEntityResolver() {
if (this.entityResolver == null) {
// Determine default EntityResolver to use.
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader != null) {
this.entityResolver = new ResourceEntityResolver(resourceLoader);
}
else {
this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());
}
}
return this.entityResolver;
}

下面在DelegatingEntityResolver:

public DelegatingEntityResolver(ClassLoader classLoader) {
//DTD验证EntityResolver
this.dtdResolver = new BeansDtdResolver();
//XSD验证EntityResolver
this.schemaResolver = new PluggableSchemaResolver(classLoader);
}

在EntityResolver指定本地验证文件的位置,如果找不到,再通过systemId的位置去找。

以上就得到了org.w3c.dom.Document,不算太曲折!

最后

以上就是平常大白为你收集整理的spring源码(1)从xml到org.w3c.dom.Document一、XmlBeanFactory的构造函数二、XmlBeanDefinitionReader读取XML的全部内容,希望文章能够帮你解决spring源码(1)从xml到org.w3c.dom.Document一、XmlBeanFactory的构造函数二、XmlBeanDefinitionReader读取XML所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(32)

评论列表共有 0 条评论

立即
投稿
返回
顶部