springはドキュメントをBeanDefinitionに解析します

前に書く

、この記事で、ドキュメントのドキュメントにXMLファイルからの解析のプロセスを分析している。本稿では、BeanDefinitionにドキュメントからパースのプロセスを分析していきます。

1:役割

春のBeanの生成に備えて、春にxmlデータ構造をBeanDefinitionデータ構造としてロードします。

2:テストコード

デバッグを容易にしてからテストコードを貼り付けるには、次のようにします。

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

テストコードを実行すると、次のコードが実行されます。

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    
    
	// 创建bean定义文档读取器
	BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
	// 已经存在的BeanDefinition的个数
	int countBefore = getRegistry().getBeanDefinitionCount();
	// 使用documentReader通过document注册BeanDefinition
	documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
	// 当前的BeanDefinition的个数减去之前存在的个数,就是新增的个数
	return getRegistry().getBeanDefinitionCount() - countBefore;
}

3:createReaderContext

ソースコード:

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createReaderContext
public XmlReaderContext createReaderContext(Resource resource) {
    
    
	return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
			this.sourceExtractor, this, getNamespaceHandlerResolver());
}

最初にそれを掘り下げないようにしましょう。

4:createBeanDefinitionDocumentReader

ソースコード:

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createBeanDefinitionDocumentReader
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
    
    
	// 	private Class<? extends BeanDefinitionDocumentReader> documentReaderClass =
    // DefaultBeanDefinitionDocumentReader.class;
	return BeanUtils.instantiateClass(this.documentReaderClass);
}

DefaultBeanDefinitionDocumentReaderは、BeanDefinitionDocumentReaderインターフェースの実装クラスであり、ドキュメントオブジェクトからBeanDefinitionを登録する機能を完了します。

5:registerBeanDefinitions

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#registerBeanDefinitionsBeanDefinitionを登録する機能は、メソッドを呼び出すことで完了ます。ソースコードは次のとおりです。

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#registerBeanDefinitions
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    
    
	this.readerContext = readerContext;
	// 调用doRegisterBeanDefinitions并获取根元素作为参数,这里是<beans>元素
	doRegisterBeanDefinitions(doc.getDocumentElement());
}

引き続きソースコードを確認してください。

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions
protected void doRegisterBeanDefinitions(Element root) {
    
    
	BeanDefinitionParserDelegate parent = this.delegate;
	// <2021-02-28 05:52>
	this.delegate = createDelegate(getReaderContext(), root, parent);
	// <2021-02-28 05:53>
	// 获取是否为根元素,其实就是判断命名空间值为http://www.springframework.org/schema/beans/
	if (this.delegate.isDefaultNamespace(root)) {
    
    
		// 获取profiles属性的值,profile是用来设置生效的环境变量的
		// 和spring.active.profiles,spring.active.default配套
		// 使用的,一般为空,如果是配置了则进一步判断是否满足环境变量
		// 要求,如果是不满足则不加载,满足则继续
		String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
		// 配置了profile
		if (StringUtils.hasText(profileSpec)) {
    
    
			// 获取配置的profile信息
			String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
					profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			// 如果是环境变量中设置的spring.active.prifle,或者是
			// spring.active.default和当前根元素中设置的相同则不return,然后继续加载工作,否则return
			if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
    
    
				if (logger.isDebugEnabled()) {
    
    
					logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
							"] not matching: " + getReaderContext().getResource());
				}
				return;
			}
		}
	}
	// 解析前处理,目前为空方法,留给子类扩展使用
	preProcessXml(root);
	// <2021-02-28 07:16>
	// 解析
	parseBeanDefinitions(root, this.delegate);
	// 解析后处理,目前是空方法,留给子类扩展使用
	postProcessXml(root);

	this.delegate = parent;
}

<2021-02-28 05:53>プロファイル情報を処理します。構成されたプロファイルが環境変数に設定されていない場合、次のxmlに示すように、ロードされません。

<?xml version="1.0" encoding="UTF-8"?>
<beans profile="gagagagaga" 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>

これ<beans>ルートタグで設定さprofile="gagagagaga"ます。次のテストコードは、対応する環境変数を設定するためのコードに注釈を付けているため、Beanはロードされません。

@Test
public void testBeanDefinitionLoad() {
    
    
    // System.setProperty("spring.profiles.active", "gagagagaga");
    // 定义资源
    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);
}

コードSystem.setProperty("spring.profiles.active", "gagagagaga");がコメントアウトされていることに注意してください。デバッグを実行すると、return:
ここに画像の説明を挿入します
runと入力します。ロードされたBeanDefinitionの数が0であることがわかります。

bean定义的个数是:0

コメントコードをSystem.setProperty("spring.profiles.active", "gagagagaga");手放すと通常どおりにロードして、次のコマンドを実行できます。

bean定义的个数是:2

<2021-02-28 05:52>ローカルコードはBeanDefinitionParserDelegateオブジェクトを取得します。オブジェクトはより重要であり、解析を担当します。<2021-02-28 07:16>ソースコードは次のとおりです。

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    
    
	// 如果是默认命名空间,即命名空间为http://www.springframework.org/schema/beans/
	if (delegate.isDefaultNamespace(root)) {
    
    
		// 获取所有的子节点
		NodeList nl = root.getChildNodes();
		// 遍历所有的子节点
		for (int i = 0; i < nl.getLength(); i++) {
    
    
			Node node = nl.item(i);
			// 如果是Element类型
			if (node instanceof Element) {
    
    
				// 强转为Element
				Element ele = (Element) node;
				// 如果是默认命名空间标签,即值为
				// http://www.springframework.org/schema/beans/
				if (delegate.isDefaultNamespace(ele)) {
    
    
					// <2021-02-28 07:41>
					parseDefaultElement(ele, delegate);
				}
				else {
    
    
					// 处理非默认命名空间标签
					delegate.parseCustomElement(ele);
				}
			}
		}
	}
	else {
    
    
		// 处理非默认命名空间标签
		delegate.parseCustomElement(root);
	}
}

<2021-02-28 07:41>コードはデフォルトの要素を解析します。ソースコードは次のとおりです。

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseDefaultElement
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    
    
	// 如果是import标签
	if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
    
    
		importBeanDefinitionResource(ele);
	}
	// 如果是alias标签
	else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
    
    
		processAliasRegistration(ele);
	}
	// 如果是bean标签
	else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
    
    
		processBeanDefinition(ele, delegate);
	}
	// 如果是内嵌beans标签,则递归解析
	else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
    
    
		// recurse
		doRegisterBeanDefinitions(ele);
	}
}

Beanタグの解釈はここを参照でき、インポートラベルで解決するにはここを参照できます

おすすめ

転載: blog.csdn.net/wang0907/article/details/114218666