spring源码07: import标签解析

本节介绍一下import标签的解析,import标签用于引进新的资源文件,例如一个spring.xml需要引入redisjdbc等配置文件。主要是要像读者介绍一下递归加载的思想,包括beans标签也使用到了递归的思想,不过beans是递归加载bean,而import是递归加载资源文件。

<beans>
  <import resource="redis.xml">
  <import resource="${jdbc.url}">
<beans>
// DefaultBeanDefinitionDocumentReader.java
	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标签,解析该标签实际是递归调用doRegisterBeanDefinitions,前面提到的parent delegate
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

解析import标签

  • location 有可能等于${jdbc.url},他将被系统变量替换成对应的URL
  • 代码的核心还是loadBeanDefinitions方法的递归调用,该方法我们在spring源码03: 资源文件读取
    就曾介绍过。细心的人可能会发现参数不同,这都是重载,调用核心还是我们讲过的方法
// DefaultBeanDefinitionDocumentReader.java
protected void importBeanDefinitionResource(Element ele) {
		// 获取标签下resource属性
		String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
		if (!StringUtils.hasText(location)) {
			getReaderContext().error("Resource location must not be empty", ele);
			return;
		}

		// Resolve system properties: e.g. "${user.dir}"
		// 转化系统变量 e.g. "${jdbc.url}" 需要转化为对应地址
		location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

		// 每一个被实际加载的资源都会被加入这个set中
		// 在资源被成功加载后,通知import-processed事件哪些资源文件又被加载了
		Set<Resource> actualResources = new LinkedHashSet<>(4);

		// Discover whether the location is an absolute or relative URI
		// 判断是绝对路径还是相对路径
		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 {
				// 绝对路径,直接使用递归调用
				// 这里的loadBeanDefinitions肯定多少有点印象
				// 该函数是loadBeanDefinitions(EncodedResource encodedResource)的重载,将会递归的加载资源
				int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
				if (logger.isTraceEnabled()) {
					logger.trace("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;
				// 相对路径,则需要先验证路径下是否有文件,之后直接调用递归的loadBeanDefinitions加载文件
				Resource relativeResource = getReaderContext().getResource().createRelative(location);
				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.isTraceEnabled()) {
					logger.trace("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[0]);
		getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
	}
发布了30 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/chaitoudaren/article/details/104833507
今日推荐