Spring配置文件解析之BeanDefinitionDocumentReader详解

 更新时间:2024年02月14日 08:42:20   作者:军伟@  
这篇文章主要介绍了Spring配置文件解析之BeanDefinitionDocumentReader详解,Spring的xml配置文件解析成Document对象,接下来的解析处理工作是在BeanDefinitionDocumentReader中对Document对象进行解析,需要的朋友可以参考下

Spring中的BeanDefinitionDocumentReader

上一篇Spring配置文件解析之BeanDefinitionReader详解中我们已经了解到BeanDefinitionReader已经将Spring的xml配置文件解析成Document对象了,接下来的解析处理工作是在BeanDefinitionDocumentReader中对Document对象进行解析工作了。

BeanDefinitionDocumentReader接口及其实现类:

BeanDefinitionDocumentReader提供的方法:

public interface BeanDefinitionDocumentReader {
 
	void registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
			throws BeanDefinitionStoreException;
 
}

在 BeanDefinitionDocumentReader的实现类DefaultBeanDefinitionDocumentReader定义了对一些xml配置文件基本的元素的解析处理操作

在这里我们可能会有一个疑问,在Spring的xml配置文件中经常看到的aop等相关的配置是在什么地方解析处理的,其实他们都是通过NamespaceHandler实现类来完成的,接下来我们会对其进行详细的介绍。

在DefaultBeanDefinitionDocumentReader的registerBeanDefinitions方法中开始对Document进行解析。

	@Override
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		Element root = doc.getDocumentElement();
		doRegisterBeanDefinitions(root);
	}

在doRegisterBeanDefinitions中会创建BeanDefinitionParserDelegate来对Document进行解析

protected void doRegisterBeanDefinitions(Element root) {
		
		BeanDefinitionParserDelegate parent = this.delegate;
		//创建BeanDefinitionParserDelegate,真正xml中各种元素的解析
		this.delegate = createDelegate(getReaderContext(), root, parent);
 
		if (this.delegate.isDefaultNamespace(root)) {
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isInfoEnabled()) {
						logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}
 
		preProcessXml(root);
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);
 
		this.delegate = parent;
	}

在parseBeanDefinitions会对Node进行判断,如果是上面配置默认解析的spring标签,则会在DefaultBeanDefinitionDocumentReader中进行解析,否则的话就需要 BeanDefinitionParserDelegate来委派找到解析处理器。

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						//默认的一些标签在DefaultBeanDefinitionDocumentReader进行解析
						parseDefaultElement(ele, delegate);
					}
					else {
						//如果不是默认的就需要在通过委派模式来寻找解析处理器
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			//如果不是默认的就需要在通过委派模式来寻找解析处理器
			delegate.parseCustomElement(root);
		}
	}

在parseDefaultElement中会对一些默认的标签import,alias,bean,beans标签进行处理

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标签解析,最终还是在BeanDefinitionParserDelegate中对元素进行处理解析生成BeanDefinitionHolder,其实bean元素的解析的结果是一个BeanDefinition对象,其包含了所有的bean的属性设置,processBeanDefinition中的BeanDefinitionReaderUtils的处理结果是将BeanDefinition注册到BeanFactory中。

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		//最终还是在BeanDefinitionParserDelegate中进行元素解析
		//BeanDefinitionHolder是对BeanDefinition的封装,包括BeanDefinition,beanName,aliases
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				//处理的操作是将bean的元数据BeanDifinition注册到BeanFactory中
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

总结

BeanDefinitionDocumentReader中也没有对xml中的bean元素进行处理操作,其真正的处理操作是在BeanDefinitionParserDelegate中进行处理的,都是在为他人做嫁衣。

到此这篇关于Spring配置文件解析之BeanDefinitionDocumentReader详解的文章就介绍到这了,更多相关Spring中的BeanDefinitionDocumentReader内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java实现单词搜索迷宫游戏

    java实现单词搜索迷宫游戏

    这篇文章主要介绍了java实现单词搜索迷宫游戏,实例分析了迷宫游戏的实现技巧,需要的朋友可以参考下
    2015-05-05
  • @JsonSerialize注解的使用示例教程

    @JsonSerialize注解的使用示例教程

    在开发中,有时候某些字段需要特殊处理,比如我们有一个日期字段,当日期为NULL时给前端不返回NULL而返回为其他等信息,就需要自定义字段的序列化,这就是@JsonSerialize的用处,本文给大家介绍@JsonSerialize注解的使用,感兴趣的朋友一起看看吧
    2023-11-11
  • Thymeleaf渲染网页时中文乱码的问题及解决

    Thymeleaf渲染网页时中文乱码的问题及解决

    这篇文章主要介绍了Thymeleaf渲染网页时中文乱码的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • SpringAOP事务配置语法及实现过程详解

    SpringAOP事务配置语法及实现过程详解

    这篇文章主要介绍了SpringAOP事务配置语法及实现过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • 浅谈Java中的hashcode方法(推荐)

    浅谈Java中的hashcode方法(推荐)

    本篇文章主要介绍了Java中的hashcode方法,详细的介绍了hashCode方法的作用,具有一定的参考价值,有需要的可以了解一下。
    2016-12-12
  • Double.parseDouble()与Double.valueOf()的区别及说明

    Double.parseDouble()与Double.valueOf()的区别及说明

    这篇文章主要介绍了Double.parseDouble()与Double.valueOf()的区别及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • java 优雅关闭线程池的方案

    java 优雅关闭线程池的方案

    这篇文章主要介绍了java 优雅关闭线程池的方案,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-11-11
  • MyBatisPlus中事务处理的实现

    MyBatisPlus中事务处理的实现

    本文主要介绍了MyBatisPlus中事务处理的实现,包括事务的开启、提交、回滚等操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-07-07
  • springboot2.0以上调度器配置线程池的实现

    springboot2.0以上调度器配置线程池的实现

    这篇文章主要介绍了springboot2.0以上调度器配置线程池的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • IDEA2022 提示更新 TKK失败请检查网络连接的问题

    IDEA2022 提示更新 TKK失败请检查网络连接的问题

    这篇文章主要介绍了IDEA2022 提示:更新 TKK 失败,请检查网络连接,本文给大家分享解决方案,对idea2022提示更新TKK失败感兴趣的朋友跟随小编一起看看吧
    2022-11-11

最新评论