iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >一文详解Spring是怎么读取配置Xml文件的
  • 120
分享到

一文详解Spring是怎么读取配置Xml文件的

2024-04-02 19:04:59 120人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录spring读取配置文件DocumentElementDocumentDefaultsDefinitionSpring读取配置文件Document 在XmlBeanDefinit

Spring读取配置文件Document

XmlBeanDefinitionReader.doLoadBeanDefinitions(InputSource inputSource, Resource resource)方法中将Xml文件转换成Document对象; Document doc = doLoadDocument(inputSource, resource); 

Element

org.w3c.dom.Element 是一个接口 public interface Element extends node Spring中DefaultBeanDefinitionDocumentReader

	@Override
	public void reGISterBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		// 从Document中获取Element
		Element root = doc.getDocumentElement();
		//注册BeanDefinitions
		doRegisterBeanDefinitions(root);
	}

DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root)

protected void doRegisterBeanDefinitions(Element root) {
		BeanDefinitionParserDelegate parent = this.delegate;
		
		
		this.delegate = createDelegate(getReaderContext(), root, parent);
		//根据root查询 xml文件的命名空间是不是public static final String BEANS_NAMESPACE_URI = "Http://www.springframework.org/schema/beans";
		if (this.delegate.isDefaultNamespace(root)) {
			//省略.....
		}
		//默认空实现 子类可以重写这个方法来处理自定义xml文件
		preProcessXml(root);
		parseBeanDefinitions(root, this.delegate);
		//默认空实现 子类可以重写这个方法来处理自定义xml文件
		postProcessXml(root);

		this.delegate = parent;
	}

this.delegate = createDelegate(getReaderContext(), root, parent);里面调用 BeanDefinitionParserDelegate.initDefaults方法 1.初始化属性值 private final DocumentDefaultsDefinition defaults = new DocumentDefaultsDefinition(); 2. TODO...

public void initDefaults(Element root, BeanDefinitionParserDelegate parent) {
		// this.defaults 是一个DocumentDefaultsDefinition对象;
		populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root);
		this.readerContext.fireDefaultsRegistered(this.defaults);
	}

BeanDefinitionParserDelegate.populateDefaults方法主要是讲xml文件中的一些命名空间的基本配置转换成DocumentDefaultsDefinition 对象; 例如

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"
	default-autowire="byName" default-lazy-init="false" default-dependency-check="all" >
//parentDefaults是父类的DocumentDefaultsDefinition对象
protected void populateDefaults(DocumentDefaultsDefinition defaults, DocumentDefaultsDefinition parentDefaults, Element root) {
		//查看xml文件中默认的default-lazy-init 值;(如果xml没有显示配置 则它的值为 default)懒加载的默认值
		String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
		if (DEFAULT_VALUE.equals(lazyInit)) {
			//如果有父类,则以父类的为准,否则将返回false。
			lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE);
		}
		defaults.setLazyInit(lazyInit);
		//default-autowire-candidates
		String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE);
		if (DEFAULT_VALUE.equals(merge)) {
			// Potentially inherited from outer <beans> sections, otherwise falling back to false.
			merge = (parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE);
		}
		defaults.setMerge(merge);
		//default-autowire
		String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
		if (DEFAULT_VALUE.equals(autowire)) {
			// Potentially inherited from outer <beans> sections, otherwise falling back to 'no'.
			autowire = (parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE);
		}
		defaults.setAutowire(autowire);

		// Don't fall back to parentDefaults for dependency-check as it's no longer supported in
		// <beans> as of 3.0. Therefore, no nested <beans> would ever need to fall back to it.
		defaults.setDependencyCheck(root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE));

		if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) {
			defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE));
		}
		else if (parentDefaults != null) {
			defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates());
		}

		if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
			defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
		}
		else if (parentDefaults != null) {
			defaults.setInitMethod(parentDefaults.getInitMethod());
		}

		if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
			defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
		}
		else if (parentDefaults != null) {
			defaults.setDestroyMethod(parentDefaults.getDestroyMethod());
		}
		//这里是???
		defaults.setSource(this.readerContext.extractSource(root));
	}

DocumentDefaultsDefinition

DocumentDefaultsDefinition(文档的默认值定义)保存了 标准的Spring Xml文件中的 {@code beans} 层级的属性,这些属性是当前Xml配置中的默认全局属性值,例如 { @code default-lazy-init },{ @code default-autowire },等等。

例如:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"
	default-autowire="byName" default-lazy-init="false" default-dependency-check="all" >
###DefaultsDefinition

默认定义的标记接口,没有任何定义 ,只是单纯的标记一下;继承BeanMetadataElement类;通常具体的实现(例如DocumentDefaultsDefinition)是基于文档的默认值,例如在一个XML文档根标记级别来进行设置默认值

BeanMetadataElement

需要被实现的元数据接口,这个接口定义了Object getSource()方法,返回一个配置源对象

public class DocumentDefaultsDefinition implements DefaultsDefinition {
	//初始化懒加载
	private String lazyInit;
	//
	private String merge;
	// 自动装载的类型 
	private String autowire;
	//
	private String dependencyCheck;

	private String autowireCandidates;
	//初始化方法
	private String initMethod;
	//销毁方法
	private String destroyMethod;
	//返回配置源对象
	private Object source;
	//省略 get set ......
}

default-autowire和autowire的可选值:

可选值功能说明
no默认不使用autowiring。 必须显示的使用”“标签明确地指定bean。
byName根据属性名自动装配。此选项将检查容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配。
byType如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配。如果存在多个该类型的bean,那么将会抛出异常,并指出不能使用byType方式进行自动装配。若没有找到相匹配的bean,则什么事都不发生,属性也不会被设置。如果你不希望这样,那么可以通过设置 dependency-check=”objects”让Spring抛出异常。
constructor与byType的方式类似,不同之处在于它应用于构造器参数。如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
autodetect通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式。

解析完了一些xml中Element的默认属性,接下来就是解析Element中的子属性了 DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(root, this.delegate); 这个方法里我们主要看 delegate.parseCustomElement(ele);

	public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
		//获取命名空间
		String namespaceUri = getNamespaceURI(ele);
		//根据命名空间得到命名空间的处理类handler  如果是dubbo的uri 则返回的就是DubboNamespaceHandler
		//他们都继承自NamespaceHandlerSupport implements NamespaceHandler 
		//里面有调用了hander的init()...
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		//1.根据Element的getLocalName()得到Element的name,然后根据这个name去NamespaceHandlerSupport中的一个属性为private final Map<String, BeanDefinitionParser> parsers ;中查找对应的解析器;这个解析器是什么时候被放到这个map里面的呢?TODO...
		//2.根据对应的解析器调用  .parse(element,parserContext)进行解析	
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}

让我们来单独解析一下 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri) 首先了解一下 this.readerContext是BeanDefinitionParserDelegate中的一个属性 private final XmlReaderContext readerContext; ##XmlReaderContext

继承了ReaderContext类,并且提供了 对XmlBeanDefinitionReader 和 NamespaceHandlerResolver的访问权限;

public class XmlReaderContext extends ReaderContext {
	//可以看到 方法权限是private 的
	private final XmlBeanDefinitionReader reader;
	private final NamespaceHandlerResolver namespaceHandlerResolver;
	public XmlReaderContext(
			Resource resource, ProblemReporter problemReporter,
			ReaderEventListener eventListener, SourceExtractor sourceExtractor,
			XmlBeanDefinitionReader reader, NamespaceHandlerResolver namespaceHandlerResolver) {

		super(resource, problemReporter, eventListener, sourceExtractor);
		this.reader = reader;
		this.namespaceHandlerResolver = namespaceHandlerResolver;
	}
	//但是提供了一些访问的方法
	public final XmlBeanDefinitionReader getReader() {
		return this.reader;
	}
	public final BeanDefinitionRegistry getRegistry() {
		return this.reader.getRegistry();
	}
	public final ResourceLoader getResourceLoader() {
		return this.reader.getResourceLoader();
	}
	public final ClassLoader getBeanClassLoader() {
		return this.reader.getBeanClassLoader();
	}
	public final Environment getEnvironment() {
		return this.reader.getEnvironment();
	}
	public final NamespaceHandlerResolver getNamespaceHandlerResolver() {
		return this.namespaceHandlerResolver;
	}
		public String generateBeanName(BeanDefinition beanDefinition) {
		return this.reader.getBeanNameGenerator().generateBeanName(beanDefinition, getRegistry());
	}
	public String registerWithGeneratedName(BeanDefinition beanDefinition) {
		String generatedName = generateBeanName(beanDefinition);
		getRegistry().registerBeanDefinition(generatedName, beanDefinition);
		return generatedName;
	}
	public Document readDocumentFromString(String documentContent) {
		InputSource is = new InputSource(new StringReader(documentContent));
		try {
			return this.reader.doLoadDocument(is, getResource());
		}
		catch (Exception ex) {
			throw new BeanDefinitionStoreException("Failed to read XML document", ex);
		}
	}

1.那XmlReaderContext是什么时候被赋值的呢?我们顺着XmlReaderContext了解一下 ①. XmlBeanDefinitionReader.registerBeanDefinitions中被创建

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		//创建XmlReaderContext,然后赋值给BeanDefinitionDocumentReader中readerContext属性中
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}
public XmlReaderContext createReaderContext(Resource resource) {
		//this 最后就是 XmlReaderContext中的XmlBeanDefinitionReader属性
		return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
				this.sourceExtractor, this, getNamespaceHandlerResolver());
	}
	public NamespaceHandlerResolver getNamespaceHandlerResolver() {
		if (this.namespaceHandlerResolver == null) {
			this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
		}
		return this.namespaceHandlerResolver;
	}
	
	protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
		return new DefaultNamespaceHandlerResolver(getResourceLoader().getClassLoader());
	}

②.创建后的XmlReaderContext被当做 BeanDefinitionParserDelegate 构造函数的参数来创建BeanDefinitionParserDelegate对象

protected void doRegisterBeanDefinitions(Element root) {
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent); 
		//省略.....
		}

到此这篇关于一文详解Spring是怎么读取配置Xml文件的的文章就介绍到这了,更多相关Spring Xml文件内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 一文详解Spring是怎么读取配置Xml文件的

本文链接: https://www.lsjlt.com/news/166318.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 一文详解Spring是怎么读取配置Xml文件的
    目录Spring读取配置文件DocumentElementDocumentDefaultsDefinitionSpring读取配置文件Document 在XmlBeanDefinit...
    99+
    2024-04-02
  • java怎么读取xml配置文件
    在Java中,读取XML配置文件有多种方法,其中比较常用的是使用DOM解析器或者SAX解析器。1. 使用DOM解析器:```java...
    99+
    2023-09-11
    java
  • 一文详解测试Python读写xml配置文件
    前言: xml也是常用的配置文件格式之一,Python中的xml.etree.ElementTree模块支持解析和创建xml数据。xml格式不再赘述,本文采用参考文献1中的示例xml...
    99+
    2024-04-02
  • 怎么用dom4j读取xml配置文件
    本篇内容主要讲解“怎么用dom4j读取xml配置文件”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用dom4j读取xml配置文件”吧!实现步骤以及源码:1、写xml文件读取类读取xml文档内...
    99+
    2023-06-03
  • spring mvc如何读取xml文件数据库配置参数
    这篇文章主要为大家展示了“spring mvc如何读取xml文件数据库配置参数”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“spring mvc如何读取xml文件数据库配置参数”这篇文章吧。sp...
    99+
    2023-05-31
    springmvc xml文件 数据库
  • C#怎么读取XML文件
    这篇文章主要讲解了“C#怎么读取XML文件”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#怎么读取XML文件”吧!用C#读取XML文件源程序代码,具体如下:using Syste...
    99+
    2023-06-17
  • java怎么读取xml文件
    在Java中,可以使用Java内置的XML解析器来读取XML文件。下面是一个简单的示例: import javax.xml.pars...
    99+
    2023-10-23
    java
  • VB.NET怎么读取XML文件
    这篇文章主要介绍“VB.NET怎么读取XML文件”,在日常操作中,相信很多人在VB.NET怎么读取XML文件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”VB.NET怎么读取XML文件”的疑惑有所帮助!接下来...
    99+
    2023-06-17
  • vbscript如何读取xml格式的配置文件
    这篇文章主要为大家展示了“vbscript如何读取xml格式的配置文件”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“vbscript如何读取xml格式的配置文件”这篇文章吧。复制代码 代码如下:...
    99+
    2023-06-08
  • Spring Boot怎么读取自定义配置文件
    这篇文章给大家分享的是有关Spring Boot怎么读取自定义配置文件的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。@Value首先,会想到使用@Value注解,该注解只能去解析yaml文件中的简单类型,并绑定到...
    99+
    2023-06-15
  • 读取xml文件中的配置参数实例
    paras.xml文件<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/be...
    99+
    2023-05-31
    读取 xml 配置参数
  • SpringBootyml配置文件读取方法详解
    目录yaml介绍yaml语法规则yaml数据读取Environment读取yaml全部属性数据自定义对象封装指定数据yaml介绍 YAML(YAML Ain't Markup...
    99+
    2022-11-13
    SpringBoot读取yml配置 SpringBoot yml读取
  • 详解Spring-boot中读取config配置文件的两种方式
    了解过spring-Boot这个技术的,应该知道Spring-Boot的核心配置文件application.properties,当然也可以通过注解自定义配置文件的信息。Spring-Boot读取配置文件的方式:一.读取核心配置文件信息ap...
    99+
    2023-05-31
    spring boot config
  • spring中怎么加载xml配置文件
    这篇文章主要讲解了“spring中怎么加载xml配置文件”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“spring中怎么加载xml配置文件”吧!spring 中加载xml配置文件的方式spr...
    99+
    2023-06-03
  • Python怎么读取配置文件
    这篇文章主要讲解了“Python怎么读取配置文件”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python怎么读取配置文件”吧!一、 yaml1、 准备支持的数据类型:字典、列表、字符串、布...
    99+
    2023-07-05
  • springboot怎么读取配置文件
    在Spring Boot中,可以通过`@Value`注解、`Environment`接口、`@ConfigurationProper...
    99+
    2023-10-25
    springboot
  • 一文详解Qt如何读取和写入配置文件的数据
    目录前言1.步骤2.附上源码头文件(.h)源文件(.cpp)前言 在Qt中如何读取配置文件(.ini)中的数据呢?又是如何将数据写入到配置文件中呢 首先你要知道.ini是什么?配置文...
    99+
    2023-03-20
    Qt读取配置文件数据 Qt写入配置文件数据 Qt 配置文件数据 Qt 配置文件
  • shell怎么读取配置文件
    本篇内容介绍了“shell怎么读取配置文件”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在编写启动脚本时,涉及到读取配置文件,特地记录下sh...
    99+
    2023-07-06
  • Spring Boot怎么正确读取配置文件属性
    这篇“Spring Boot怎么正确读取配置文件属性”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Spring&n...
    99+
    2023-06-30
  • Spring Boot读取自定义配置文件
    目录@Value @ConfigurationProperties 显式注入 Spring IoC @EnableConfigurationProperties @Configura...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作