Spring源码解析 第二章、容器的基本实现

2.6  获取XML的验证方式

加载Bean的过程主要有三步,1、获取对XML的验证模式  2、加载XML文件,并且得到相应的doucument  3、根据返回的doucument来注册Bean的信息。接下来具体探讨一下Spring源码中怎么去完成的这三步。

2.6.1  DTD与XSD的区别

DTD:类型定义(Documnet Type Definition) 
DTD 是一套关于标记符的语法规则。它是XML1.0版规格得一部分,是XML文件的验证机制,属于XML文件组成的一部分。 
DTD 是一种保证XML文档格式正确的有效方法,可以通过比较XML文档和DTD文件来看文档是否符合规范,元素和标签使用是否正确。 
一个DTD文档包含:元素的定义规则,元素间关系的定义规则,元素可使用的属性,可使用的实体或符号规则。 
但是DTD 是使用非 XML 语法编写的 
DTD 不可扩展,不支持命名空间,只提供非常有限的数据类型 
XSD:XML结构定义 ( XML Schemas Definition ) 
XML Schema语言也就是XSD。XML Schema描述了XML文档的结构。 
可以用一个指定的XML Schema来验证某个XML文档,以检查该XML文档是否符合其要求。文档设计者可以通过XML Schema指定一个XML文档所允许的结构和内容,并可据此检查一个XML文档是否是有效的。XML Schema本身是一个XML文档,它符合XML语法结构。可以用通用的XML解析器解析它。 
一个XML Schema会定义:文档中出现的元素、文档中出现的属性、子元素、子元素的数量、子元素的顺序、元素是否为空、元素和属性的数据类型、元素或属性的默认和固定值。 
XSD是DTD替代者的原因,一是据将来的条件可扩展,二是比DTD丰富和有用,三是用XML书写,四是支持数据类型,五是支持命名空间。 
XML Schema的优点: 
1) XML Schema基于XML,没有专门的语法 
2) XML可以象其他XML文件一样解析和处理 
3) XML Schema支持一系列的数据类型(int、float、Boolean、date等) 
4) XML Schema提供可扩充的数据模型。 
5) XML Schema支持综合命名空间 
6) XML Schema支持属性组。

2.6.2  验证模式的读取 

之前分析过Spring通过getValidationModeForResource(resource)这个方法进入到获取XML验证模式,下面看一下这个方法的源码

protected int getValidationModeForResource(Resource resource) {
		int validationModeToUse = getValidationMode();
        //自定义的验证方式
		if (validationModeToUse != VALIDATION_AUTO) {
			return validationModeToUse;
		}
        // 如果未指定验证方式,那么将会自动检测
		int detectedMode = detectValidationMode(resource);
		if (detectedMode != VALIDATION_AUTO) {
			return detectedMode;
		}
		return VALIDATION_XSD;
	}

方法的实现其实是很简单的,无非是如果设定了验证模式则使用验证模式(可以通过调用XmlBeanDefinitionReader中的setValidationModeName(String validationModeName)来进行自定义验证),否则执行detectValidationMode(resource)使用自动检测的方式。在detectValidationMode方法中,又将自动检测的验证模式委托给了ValidationModeDetector类,调用了detectValidationMode的方法。

protected int detectValidationMode(Resource resource) {1
		if (resource.isOpen()) {
			throw new BeanDefinitionStoreException(
					"Passed-in Resource [" + resource + "] contains an open stream: " +
					"cannot determine validation mode automatically. Either pass in a Resource " +
					"that is able to create fresh streams, or explicitly specify the validationMode " +
					"on your XmlBeanDefinitionReader instance.");
		}

		InputStream inputStream;
		try {
			inputStream = resource.getInputStream();
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"Unable to determine validation mode for [" + resource + "]: cannot open InputStream. " +
					"Did you attempt to load directly from a SAX InputSource without specifying the " +
					"validationMode on your XmlBeanDefinitionReader instance?", ex);
		}
        //委托了validationModeDetector
		try {
			return this.validationModeDetector.detectValidationMode(inputStream);
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException("Unable to determine validation mode for [" +
					resource + "]: an error occurred whilst reading from the InputStream.", ex);
		}
	}
	public int detectValidationMode(InputStream inputStream) throws IOException {
		// Peek into the file to look for DOCTYPE.
		BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
		try {
			boolean isDtdValidated = false;
			String content;
			while ((content = reader.readLine()) != null) {
                    //获取到得内容,如果是空或者是注释得话,略过
				content = consumeCommentTokens(content);
				if (this.inComment || !StringUtils.hasText(content)) {
					continue;
				}
				if (hasDoctype(content)) {
					isDtdValidated = true;
					break;
				}
                //当读到<这个得时候,则进行开始验证了,因为dtd,xsd都是以<开始的
				if (hasOpeningTag(content)) {
					// End of meaningful data...
					break;
				}
			}
			return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
		}
		catch (CharConversionException ex) {
			// Choked on some character encoding...
			// Leave the decision up to the caller.
			return VALIDATION_AUTO;
		}
		finally {
			reader.close();
		}
	}

其实自动检测的业务逻辑很简单,就是判断是否包含DOCTYPE,如果包含就是DTD验证方式,否则就是XSD

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值