Análisis del modelo de verificación de primavera IOC

Escribir al frente

En este trabajo, el artículo continuó sobre la base del análisis, como complemento.

1: Rol

La función de la verificación es garantizar la corrección del archivo xml. Solo cuando el archivo xml es completamente correcto, pueden continuar las operaciones subsiguientes, como la carga de definiciones de bean.

2: mecanismo de verificación xml

Los mecanismos de verificación xml actuales incluyen DTD (Definición de tipo de documento) y XSD (Definición de esquema Xml). El primero es anterior y XSD es posterior, debido a los diversos defectos de DTD (como menos tipos de datos, escalabilidad débil, XML no estándar formato, lo que resulta en un análisis difícil), se ha eliminado, XSD se ha convertido en la corriente principal.

3: proceso de verificación

Para facilitar la depuración y luego pegar el código de prueba:

@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>

La última llamada al código:

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());
}

El método llama internamente al método para getValidationModeForResourceobtener el modo de verificación. El código fuente es el siguiente:

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>El código fuente es el siguiente:

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

<2021-02-25 12:21>Obtenga el método de verificación del archivo xml, el código fuente es el siguiente:

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>Aquí está la ubicación del modo de verificación.

3.1: XmlValidationModeDetector

Este es un objeto independiente sin subclases ni clases principales 当然排除java.lang.Object后. Esta parte explica el <2021-02-25 14:40>código, el código fuente es el siguiente:

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();
	}
}

Luego, a través de aquí , vea cómo se carga el recurso como un objeto de documento Documento.

Supongo que te gusta

Origin blog.csdn.net/wang0907/article/details/114025933
Recomendado
Clasificación