Analysis of the verification model of spring IOC

Write in front

In this paper, the article continued on the basis of the analysis, as a supplement.

1: Role

The role of verification is to ensure the correctness of the xml file. Only when the xml file is completely correct can subsequent operations such as loading bean definitions continue.

2: xml verification mechanism

The current xml verification mechanisms include DTD (Document Type Definition) and XSD (Xml Schema Definition). The former is earlier and XSD is later, because of the various defects of DTD (such as less data types, weak scalability, non-standard xml format, resulting in parsing Difficult), has been eliminated, XSD has become the mainstream.

3: Verification process

In order to facilitate debugging and then paste the test code:

@Test
public void testBeanDefinitionLoad() {
    
    
    // 定义资源
    ClassPathResource classPathResource = new ClassPathResource("testbeandefinition.xml");
    // 定义IOC容器
    DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
    // 定义bean定义读取器
    XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
    // 通过bean定义读取器从资源中读取bean定义
    int i = xmlBeanDefinitionReader.loadBeanDefinitions(classPathResource);
    System.out.println("bean定义的个数是:" + i);
}

xml:

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

    <bean id="testBeanDefinitionBean"
          class="yudaosourcecode.spring.TestBeanDefinitionBean"></bean>

    <bean id="testBeanDefinitionBean1"
          class="yudaosourcecode.spring.TestBeanDefinitionBean"></bean>
    <!-- 这里引入自己的话会发生org.springframework.beans.factory.BeanDefinitionStoreException异常 -->
    <!--<import resource="testbeandefinition.xml"/>-->
</beans>

The final call to the code:

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadDocument
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
    
    
	return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
			getValidationModeForResource(resource), isNamespaceAware());
}

The method internally calls the method to getValidationModeForResourceobtain the verification mode. The source code is as follows:

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#getValidationModeForResource
protected int getValidationModeForResource(Resource resource) {
    
    
	// <2021-02-25 12:16> 获取设置的验证模式
	int validationModeToUse = getValidationMode();
	// 如果是设置的验证模式不是VALIDATION_AUTO,
	// private int validationMode = VALIDATION_AUTO;
	// public static final int VALIDATION_AUTO = XmlValidationModeDetector.VALIDATION_AUTO;
	// public static final int VALIDATION_AUTO = 1;
	// 则使用,否则继续
	if (validationModeToUse != VALIDATION_AUTO) {
    
    
		return validationModeToUse;
	}
	// <2021-02-25 12:21> 从资源中自动获取验证模式
	int detectedMode = detectValidationMode(resource);
	// 不是自动则使用自动获取的
	if (detectedMode != VALIDATION_AUTO) {
    
    
		return detectedMode;
	}
	// 手动也没有设置,自动也没有获取到,则默认XSD
	// public static final int VALIDATION_XSD = XmlValidationModeDetector.VALIDATION_XSD;
	// org.springframework.util.xml.XmlValidationModeDetector#VALIDATION_XSD
	// public static final int VALIDATION_XSD = 3;
	return VALIDATION_XSD;
}

<2021-02-25 12:16>The source code is as follows:

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#getValidationMode
public int getValidationMode() {
    
    
	// 默认值为自动验证模式
	// private int validationMode = VALIDATION_AUTO;
	return this.validationMode;
}

<2021-02-25 12:21>Obtain the verification method from the xml file, the source code is as follows:

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#detectValidationMode
protected int detectValidationMode(Resource resource) {
    
    
	// 不可读,抛出BeanDefinitionStoreException
	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) {
    
    
		...snip throw ex...
	}

	try {
    
    
		// <2021-02-25 14:40>这里为真正获取验证模式位置
		return this.validationModeDetector.detectValidationMode(inputStream);
	}
	catch (IOException ex) {
    
    
		...snip throw ex...
	}
}

<2021-02-25 14:40>Here is to actually get the location of the verification mode.

3.1:XmlValidationModeDetector

This is an independent object with no subclasses and no parent classes 当然排除java.lang.Object后. This part explains the <2021-02-25 14:40>code, the source code is as follows:

public int detectValidationMode(InputStream inputStream) throws IOException {
    
    
	// Peek into the file to look for DOCTYPE.
	BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
	try {
    
    
		// 默认是dtd
		boolean isDtdValidated = false;
		String content;
		// 循环每一行进行判断
		while ((content = reader.readLine()) != null) {
    
    
			// 处理注释
			content = consumeCommentTokens(content);
			// 如果被注释包裹或者是没有内容,则continue
			if (this.inComment || !StringUtils.hasText(content)) {
    
    
				continue;
			}
			// 如果是有DOCTYPE关键字,则认为是dtd,这里一般为false
			// 如下就是包含DOCTYPE的情况
			// <?xml version="1.0" encoding="UTF-8"?>
			// <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
			if (hasDoctype(content)) {
    
    
				isDtdValidated = true;
				break;
			}
			// 如果是以<开头,并且紧接着的是一个字母,则为true,因为不是我们需要的,而是正常的定义内容,如<bean...
			if (hasOpeningTag(content)) {
    
    
				// End of meaningful data...
				break;
			}
		}
		// 如果是isDtdValidated为true则返回dtd,否则xsd
		return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
	}
	catch (CharConversionException ex) {
    
    
		// 发生异常则返回自动验证模式
		return VALIDATION_AUTO;
	}
	finally {
    
    
		reader.close();
	}
}

Then through here , see how the resource is loaded as a Document document object.

Guess you like

Origin blog.csdn.net/wang0907/article/details/114025933