spring source 07: import tag parsing

Posted by ehask on Sat, 14 Mar 2020 18:06:46 +0100

This section introduces the analysis of import tag, which is used to introduce new resource files, such as redis, jdbc and other configuration files for a spring.xml. It is mainly to introduce the idea of recursive loading to the readers, including the idea that the beans tag also uses recursion, but beans is a recursive loading bean, and import is a recursive loading resource file.

<beans>
  <import resource="redis.xml">
  <import resource="${jdbc.url}">
<beans>
// DefaultBeanDefinitionDocumentReader.java
	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		// Parsing import Tags
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		// Parsing alias Tags
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		// Parsing bean Tags
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		// Parsing the beans tag is actually a recursive call to doRegisterBeanDefinitions, the parent delegate mentioned earlier
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

Parsing import Tags

  • location may be equal to ${jdbc.url}, which will be replaced with the corresponding URL by the system variable
  • The core of the code is also a recursive call to the loadBeanDefinitions method, which we call in the spring source 03: resource file reading
    It was introduced. Careful people may find that the parameters are different. This is all overloading. Is it the core of calling or the method we talked about
// DefaultBeanDefinitionDocumentReader.java
protected void importBeanDefinitionResource(Element ele) {
		// Get the resource attribute under the tag
		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}"
		// Converting the system variable e.g. "${jdbc.url}" needs to be converted to the corresponding address
		location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

		// Every resource actually loaded will be added to this set
		// After the resource is loaded successfully, inform the import processed event which resource files are loaded again
		Set<Resource> actualResources = new LinkedHashSet<>(4);

		// Discover whether the location is an absolute or relative URI
		// Judge absolute path or relative path
		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 {
				// Absolute path, directly using recursive call
				// The load bean definitions here must be a little impressive
				// This function is an overload of loadbean definitions (encodedresource encodedresource), which will load resources recursively
				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;
				// Relative path, you need to verify whether there is a file under the path, and then directly call the recursive loadBeanDefinitions to load the file
				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));
	}
Published 20 original articles, won praise 5, visited 6223
Private letter follow

Topics: JDBC Spring Redis xml