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)); }