In the last post, we go through the whole process about how to register a regular <bean>. Now, let's take a look at how to load <import> tag:
importBeanDefinitionResource has all the implementation.
the logic is as following:
1. get the value of attribute: resource
2. resolve the location string by replacing system properties: e.g. "${user.dir}"
3. check the location is starting with classpath or regular url.
4. Line 26 will use AbstractBeanDefinitionReader->loadBeanDefinitions to parse the spring beans as mentioned in my previous blog.
5. The actualResources is used to store all loaded resources.
6. Line 63 will trig the event of import definition done.
<import resource="services.xml"/> <import resource="resources/messageSource.xml"/> <import resource="/resources/themeSource.xml"/>
</import>
see the entry code here:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { | |
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { | |
importBeanDefinitionResource(ele); | |
} | |
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { | |
processAliasRegistration(ele); | |
} | |
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { | |
processBeanDefinition(ele, delegate); | |
} | |
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { | |
// recurse | |
doRegisterBeanDefinitions(ele); | |
} | |
} |
importBeanDefinitionResource has all the implementation.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
// Resolve system properties: e.g. "${user.dir}" | |
location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location); | |
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 { | |
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; | |
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)); | |
} |
1. get the value of attribute: resource
2. resolve the location string by replacing system properties: e.g. "${user.dir}"
3. check the location is starting with classpath or regular url.
4. Line 26 will use AbstractBeanDefinitionReader->loadBeanDefinitions to parse the spring beans as mentioned in my previous blog.
- get the file resource list (if the location path contains "*" or "?") or return the file resource directly.
- parse the resource to spring bean one by one.
5. The actualResources is used to store all loaded resources.
6. Line 63 will trig the event of import definition done.
Comments
Post a Comment