欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文詳解Spring是怎么讀取配置Xml文件的

 更新時間:2022年08月30日 09:26:45   作者:石臻臻的雜貨鋪???????  
這篇文章主要介紹了一文詳解Spring是怎么讀取配置Xml文件的,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下

Spring讀取配置文件Document

XmlBeanDefinitionReader.doLoadBeanDefinitions(InputSource inputSource, Resource resource)方法中將Xml文件轉(zhuǎn)換成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;
		
		/**
		1.根據(jù)Element root創(chuàng)建**BeanDefinitionParserDelegate**對象
		2.解析Xml文件頭中的一些屬性配置到 BeanDefinitionParserDelegate屬性(DocumentDefaultsDefinition)defaults;
		**/
		this.delegate = createDelegate(getReaderContext(), root, parent);
		//根據(jù)root查詢 xml文件的命名空間是不是public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans";
		if (this.delegate.isDefaultNamespace(root)) {
			//省略.....
		}
		//默認空實現(xiàn) 子類可以重寫這個方法來處理自定義xml文件
		preProcessXml(root);
		parseBeanDefinitions(root, this.delegate);
		//默認空實現(xiàn) 子類可以重寫這個方法來處理自定義xml文件
		postProcessXml(root);

		this.delegate = parent;
	}

this.delegate = createDelegate(getReaderContext(), root, parent);里面調(diào)用 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文件中的一些命名空間的基本配置轉(zhuǎn)換成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)) {
			//如果有父類,則以父類的為準(zhǔn),否則將返回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(文檔的默認值定義)保存了 標(biāo)準(zhǔn)的Spring Xml文件中的 {@code beans} 層級的屬性,這些屬性是當(dāng)前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

默認定義的標(biāo)記接口,沒有任何定義 ,只是單純的標(biāo)記一下;繼承BeanMetadataElement類;通常具體的實現(xiàn)(例如DocumentDefaultsDefinition)是基于文檔的默認值,例如在一個XML文檔根標(biāo)記級別來進行設(shè)置默認值

BeanMetadataElement

需要被實現(xiàn)的元數(shù)據(jù)接口,這個接口定義了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。 必須顯示的使用”“標(biāo)簽明確地指定bean。
byName根據(jù)屬性名自動裝配。此選項將檢查容器并根據(jù)名字查找與屬性完全一致的bean,并將其與屬性自動裝配。
byType如果容器中存在一個與指定屬性類型相同的bean,那么將與該屬性自動裝配。如果存在多個該類型的bean,那么將會拋出異常,并指出不能使用byType方式進行自動裝配。若沒有找到相匹配的bean,則什么事都不發(fā)生,屬性也不會被設(shè)置。如果你不希望這樣,那么可以通過設(shè)置 dependency-check=”objects”讓Spring拋出異常。
constructor與byType的方式類似,不同之處在于它應(yīng)用于構(gòu)造器參數(shù)。如果在容器中沒有找到與構(gòu)造器參數(shù)類型一致的bean,那么將會拋出異常。
autodetect通過bean類的自省機制(introspection)來決定是使用constructor還是byType方式進行自動裝配。如果發(fā)現(xiàn)默認的構(gòu)造器,那么將使用byType方式。

解析完了一些xml中Element的默認屬性,接下來就是解析Element中的子屬性了 DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(root, this.delegate); 這個方法里我們主要看 delegate.parseCustomElement(ele);

	public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
		//獲取命名空間
		String namespaceUri = getNamespaceURI(ele);
		//根據(jù)命名空間得到命名空間的處理類handler  如果是dubbo的uri 則返回的就是DubboNamespaceHandler
		//他們都繼承自NamespaceHandlerSupport implements NamespaceHandler 
		//里面有調(diào)用了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.根據(jù)Element的getLocalName()得到Element的name,然后根據(jù)這個name去NamespaceHandlerSupport中的一個屬性為private final Map<String, BeanDefinitionParser> parsers ;中查找對應(yīng)的解析器;這個解析器是什么時候被放到這個map里面的呢?TODO...
		//2.根據(jù)對應(yīng)的解析器調(diào)用  .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的訪問權(quán)限;

public class XmlReaderContext extends ReaderContext {
	//可以看到 方法權(quán)限是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中被創(chuàng)建

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		//創(chuàng)建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;
	}
	/**
	*如果沒有具體的實現(xiàn)類,則創(chuàng)建 默認的實現(xiàn)類返回
	* 默認的實現(xiàn)類DefaultNamespaceHandlerResolver中的handlerMappingsLocation屬性(Resource location to search for)=META-INF/spring.handlers
	*/
	protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
		return new DefaultNamespaceHandlerResolver(getResourceLoader().getClassLoader());
	}

②.創(chuàng)建后的XmlReaderContext被當(dāng)做 BeanDefinitionParserDelegate 構(gòu)造函數(shù)的參數(shù)來創(chuàng)建BeanDefinitionParserDelegate對象

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

到此這篇關(guān)于一文詳解Spring是怎么讀取配置Xml文件的的文章就介紹到這了,更多相關(guān)Spring Xml文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot整合RabbitMQ消息隊列的完整步驟

    SpringBoot整合RabbitMQ消息隊列的完整步驟

    這篇文章主要給大家介紹了關(guān)于SpringBoot整合RabbitMQ消息隊列的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • idea maven 構(gòu)建本地jar包及pom文件的過程

    idea maven 構(gòu)建本地jar包及pom文件的過程

    這篇文章主要介紹了idea maven 構(gòu)建本地jar包及pom文件的過程,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-11-11
  • springboot結(jié)合全局異常處理實現(xiàn)登錄注冊驗證

    springboot結(jié)合全局異常處理實現(xiàn)登錄注冊驗證

    這篇文章主要介紹了springboot結(jié)合全局異常處理實現(xiàn)登錄注冊驗證,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-05-05
  • Mybatis多表關(guān)聯(lián)查詢的實現(xiàn)(DEMO)

    Mybatis多表關(guān)聯(lián)查詢的實現(xiàn)(DEMO)

    本節(jié)要實現(xiàn)的是多表關(guān)聯(lián)查詢的簡單demo。場景是根據(jù)id查詢某商品分類信息,并展示該分類下的商品列表,需要的朋友可以參考下
    2017-02-02
  • 精通Java List 按字段提取對象

    精通Java List 按字段提取對象

    這篇文章主要介紹了精通Java List 按字段提取對象的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • 微服務(wù)如何通過feign.RequestInterceptor傳遞參數(shù)

    微服務(wù)如何通過feign.RequestInterceptor傳遞參數(shù)

    這篇文章主要介紹了微服務(wù)如何通過feign.RequestInterceptor傳遞參數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • springboot整合Mybatis-plus的實現(xiàn)

    springboot整合Mybatis-plus的實現(xiàn)

    這篇文章主要介紹了springboot整合Mybatis-plus的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Springboot Caffeine本地緩存使用示例

    Springboot Caffeine本地緩存使用示例

    這篇文章主要介紹了Springboot Caffeine本地緩存使用示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11
  • Java隨機密碼生成并和郵箱、手機號匹配

    Java隨機密碼生成并和郵箱、手機號匹配

    這篇文章主要介紹了Java隨機密碼生成并和郵箱、手機號匹配的相關(guān)資料,需要的朋友可以參考下
    2016-01-01
  • java?使用BeanFactory實現(xiàn)service與dao層解耦合詳解

    java?使用BeanFactory實現(xiàn)service與dao層解耦合詳解

    這篇文章主要介紹了java?使用BeanFactory實現(xiàn)service與dao層解耦合詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12

最新評論