Le fichier de configuration Spring est chargé en tant qu'analyse de processus BeanDefinition

1: écrire devant

Dans le travail réel, je peux souvent écrire le code suivant:

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

Le contenu du fichier de configuration utilisé est le suivant:

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

Cet élément de code charge les informations de bean dans le fichier de configuration en tant que BeanDefinition in spring, qui est la structure de données qui stocke les informations de bean que nous avons définies au printemps. La dernière génération de spring beans dépend également de cette structure de données. Le résultat final en cours d'exécution du code est le suivant:

bean定义的个数是:2

Ce qui est renvoyé est le nombre de beans définis dans le fichier de configuration.

2 : loadBeanDefinitions

Cette méthode complète la fonction de chargement de définition de bean à partir de la ressource encapsulée avec le fichier de configuration, l'emplacement spécifique est le suivant:

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource)
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    
    
	// 其中EncodedResource是加了编码的资源,不影响主流程,可以无视
	return loadBeanDefinitions(new EncodedResource(resource));
}

continuer:

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.support.EncodedResource)
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    
    
	// 断言判断传入的资源不为null
	Assert.notNull(encodedResource, "EncodedResource must not be null");
	if (logger.isTraceEnabled()) {
    
    
		logger.trace("Loading XML bean definitions from " + encodedResource);
	}
	// <2021-02-24 12:21>
	// 从resourcesCurrentlyBeingLoaded中获取当前线程已经或者是正在加载的资源集合
	Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
	// 如果是不存在已经加载的资源则创建,注意这里是
	// 使用的HashSet,因为资源不允许重复
	if (currentResources == null) {
    
    
		currentResources = new HashSet<>(4);
		// 存储新创建的资源到resourcesCurrentlyBeingLoaded中
		this.resourcesCurrentlyBeingLoaded.set(currentResources);
	}
	// <2021-02-24 12:23>
	// 这里如果是资源在set集合中已经存在会返回false,此时代表资源重复
	// 直接抛出BeanDefinitionStoreException信息
	if (!currentResources.add(encodedResource)) {
    
    
		throw new BeanDefinitionStoreException(
				"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
	}
	try {
    
    
		// 获取对应的资源,然后从资源中获取输入流
		InputStream inputStream = encodedResource.getResource().getInputStream();
		try {
    
    
			// 封装到InputSource中
			InputSource inputSource = new InputSource(inputStream);
			// 如果有编码则使用,不影响主流程,可以忽略
			if (encodedResource.getEncoding() != null) {
    
    
				inputSource.setEncoding(encodedResource.getEncoding());
			}
			// <2021-02-24 12:27>
			// 实现具体加载为BeanDefinition的过程
			return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
		}
		finally {
    
    
			inputStream.close();
		}
	}
	catch (IOException ex) {
    
    
		throw new BeanDefinitionStoreException(
				"IOException parsing XML document from " + encodedResource.getResource(), ex);
	}
	finally {
    
    
		// 删除资源
		currentResources.remove(encodedResource);
		// 如果删除当前资源后,没有其他资源,则清空threadlocal
		if (currentResources.isEmpty()) {
    
    
			this.resourcesCurrentlyBeingLoaded.remove();
		}
	}
}

<2021-02-24 12:21>La variable est définie comme private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded = new NamedThreadLocal<>("XML bean definition resources currently being loaded");une sous-classe NamedThreadLocalde java.lang.ThreadLocalla classe, mais l'attribut du nom est ajouté. Le code source est le suivant:

public class NamedThreadLocal<T> extends ThreadLocal<T> {
    
    

	private final String name;

	public NamedThreadLocal(String name) {
    
    
		Assert.hasText(name, "Name must not be empty");
		this.name = name;
	}

	@Override
	public String toString() {
    
    
		return this.name;
	}
}

<2021-02-24 12:23>Le but est de juger si la ressource existe, principalement pour faire face à la situation de se présenter, de sorte qu'une boucle infinie d'introduction de ressources se produise, alors traitez-la, la situation suivante sera une boucle infinie:
Insérez la description de l'image ici
testez et exécutez ce qui suit code:

@Test
public void testBeanDefinitionStoreException() {
    
    
    // 定义资源
    ClassPathResource classPathResource = new ClassPathResource("testbeandefinition.xml");
    // 定义IOC容器
    DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
    // 定义bean定义读取器
    XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
    // 通过bean定义读取器从资源中读取bean定义
    xmlBeanDefinitionReader.loadBeanDefinitions(classPathResource);
}

Fonctionnement anormal: le
Insérez la description de l'image ici
<2021-02-24 12:27>code source est le suivant:

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
    
    
	try {
    
    
		// <2021-02-24 16:01> 获取xml文件对应的文档对象
		Document doc = doLoadDocument(inputSource, resource);
		// <2021-02-24 16:02> 根据文档对象注册Bean信息
		int count = registerBeanDefinitions(doc, resource);
		if (logger.isDebugEnabled()) {
    
    
			logger.debug("Loaded " + count + " bean definitions from " + resource);
		}
		return count;
	}
	catch (BeanDefinitionStoreException ex) {
    
    
		throw ex;
	}
	catch (SAXParseException ex) {
    
    
		...snip...
	}
	catch (SAXException ex) {
    
    
		...snip...
	}
	catch (ParserConfigurationException ex) {
    
    
		...snip...
	}
	catch (IOException ex) {
    
    
		...snip...
	}
	catch (Throwable ex) {
    
    
		...snip...
	}
}

<2021-02-24 16:01>Le code source est le suivant:

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

Le code getValidationModeForResource(resource)est pour obtenir le modèle de vérification, vous pouvez vous référer ici pour plus de détails . Le code this.documentLoader.loadDocumentconsiste à obtenir l'instance de Document correspondant au fichier XML. Pour plus de détails, reportez-vous ici . <2021-02-24 16:02>, Enregistrez les informations BeanDefinition conformément aux informations du document Document, reportez-vous ici pour plus de détails .

Je suppose que tu aimes

Origine blog.csdn.net/wang0907/article/details/114016448
conseillé
Classement