spring-mvc源碼-bean定義加載-默認標籤解析(import)

import標籤的解析是調用的org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#importBeanDefinitionResource方法,源碼如下:

	protected void importBeanDefinitionResource(Element ele) {
		String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
		if (!StringUtils.hasText(location)) {
			getReaderContext().error("Resource location must not be empty", ele);
			return;
		}

		//從上下文獲取系統屬性,解析${}佔位符並使用相應的屬性值來代替
		location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

		Set<Resource> actualResources = new LinkedHashSet<Resource>(4);

		//這裏是對import的位置做出判斷,是相對還是絕對路徑,默認是相對
		boolean absoluteLocation = false;
		try {
			absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
		}
		catch (URISyntaxException ex) {
			// cannot convert to an URI, considering the location relative
			// unless it is the well-known Spring prefix "classpath*:"
		}

		// Absolute or relative?
		if (absoluteLocation) {
			try {
				int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
				if (logger.isDebugEnabled()) {
					logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
				}
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error(
						"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
			}
		}
		else {
			// No URL -> considering resource location as relative to the current file.
			try {
				int importCount;
				//將路徑配置轉爲資源
				Resource relativeResource = getReaderContext().getResource().createRelative(location);
				//如果可以獲取到資源,則回調到AbstractBeanDefinitionReader的loadBeanDefinitions方法進行加載
				if (relativeResource.exists()) {
					importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
					actualResources.add(relativeResource);
				}
				else {
					//獲取不到資源,則加上基礎路徑,再進行加載操作
					String baseLocation = getReaderContext().getResource().getURL().toString();
					importCount = getReaderContext().getReader().loadBeanDefinitions(
							StringUtils.applyRelativePath(baseLocation, location), actualResources);
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
				}
			}
			catch (IOException ex) {
				getReaderContext().error("Failed to resolve current resource location", ele, ex);
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
						ele, ex);
			}
		}
		Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
		//調用事件監聽器ReaderEventListener#importProcessed()方法 通知處理的import的結果
		getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
	}

其中有一步獲取系統屬性,解析${}佔位符並使用相應的屬性值來代替,這個的主要場景是資源文件可能是按環境分離的,如:

<import resource="com/test/dao/dao-${test}.xml" />

這裏可以從系統屬性和環境變量中獲取,類似於:System.getProperties(),System.getenv()

這些屬性,在上下文中已經存在,

如系統屬性:

os.name

如環境變量:

JAVA_HOME

最後一步,都會調到org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource)這個方法解析xml文件,具體解析又回到了bean的定義加載,因爲本身也在解析xml文件流程中,只是裏面又嵌套了xml文件,遞歸調用,可看這篇文章:https://blog.csdn.net/matt8/article/details/106352083

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章