actualResources)`, 方法。该方法在 `org.springframework.beans.factory.support.AbstractBeanDefinitionReader` 中定义,代码如下:
```
/**
* Load bean definitions from the specified resource location.
* The location can also be a location pattern, provided that the
* ResourceLoader of this bean definition reader is a ResourcePatternResolver.
* @param location the resource location, to be loaded with the ResourceLoader
* (or ResourcePatternResolver) of this bean definition reader
* @param actualResources a Set to be filled with the actual Resource objects
* that have been resolved during the loading process. May be {@code null}
* to indicate that the caller is not interested in those Resource objects.
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of loading or parsing errors
* @see #getResourceLoader()
* @see #loadBeanDefinitions(org.springframework.core.io.Resource)
* @see #loadBeanDefinitions(org.springframework.core.io.Resource[])
*/
public int loadBeanDefinitions(String location, @Nullable Set actualResources) throws BeanDefinitionStoreException {
// 获得 ResourceLoader 对象
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
// 获得 Resource 数组,因为 Pattern 模式匹配下,可能有多个 Resource 。例如说,Ant 风格的 location
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
// 加载 BeanDefinition 们
int count = loadBeanDefinitions(resources);
// 添加到 actualResources 中
if (actualResources != null) {
Collections.addAll(actualResources, resources);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
}
return count;
} catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
} else {
// Can only load single resources by absolute URL.
// 获得 Resource 对象,
Resource resource = resourceLoader.getResource(location);
// 加载 BeanDefinition 们
int count = loadBeanDefinitions(resource);
// 添加到 actualResources 中
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
}
return count;
}
}
```
整个逻辑比较简单:
- 首先,获取 ResourceLoader 对象。
- 然后,根据不同的 ResourceLoader 执行不同的逻辑,主要是可能存在多个 Resource 。
- 最终,都会回归到 `XmlBeanDefinitionReader#loadBeanDefinitions(Resource... resources)` 方法,所以这是一个递归的过程。
- 另外,获得到的 Resource 的对象或数组,都会添加到 `actualResources` 中。
### 2.3 处理相对路径
如果 `location` 是相对路径,则会根据相应的 Resource 计算出相应的相对路径的 Resource 对象 ,然后:
- 若该 Resource 存在,则调用 `XmlBeanDefinitionReader#loadBeanDefinitions()` 方法,进行 BeanDefinition 加载。
- 否则,构造一个绝对 `location`( 即 `StringUtils.applyRelativePath(baseLocation, location)` 处的代码),并调用 `#loadBeanDefinitions(String location, Set actualResources)` 方法,**与绝对路径过程一样**。
## 3. 小结
至此,`import` 标签解析完毕,整个过程比较清晰明了:**获取 source 属性值,得到正确的资源路径,然后调用 XmlBeanDefinitionReader#loadBeanDefinitions(Resource... resources) 方法,进行递归的 BeanDefinition 加载**。
评论区