参考文章:
import 解析
xml中import的应用
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="spring-student.xml"/>
<import resource="spring-student-dtd.xml"/>
</beans>
相关方法
importBeanDefinitionResource
protected void importBeanDefinitionResource(Element ele) {
// 读取属性
String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
// 为空则打印error退出
if (!StringUtils.hasText(location)) {
getReaderContext().error("Resource location must not be empty", ele);
return;
}
//解析系统属性,格式如 :"${user.dir}"
// Resolve system properties: e.g. "${user.dir}"
location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
// 实际 Resource 集合,即 import 的地址,有哪些 Resource 资源
Set<Resource> actualResources = new LinkedHashSet<>(4);
// 判断相对路径还是绝对路径
// Discover whether the location is an absolute or relative URI
boolean absoluteLocation = false;
try {
// classpath*: 或者 classpath: 开头的为绝对路径
// 能够通过该 location 构建出 java.net.URL 为绝对路径。
// location 构造 java.net.URI 判断调用 #isAbsolute() 方法,判断是否为绝对路径
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 {
// 添加配置文件地址的 Resource 到 actualResources 中,并加载相应的 BeanDefinition 们
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
Resource relativeResource = getReaderContext().getResource().createRelative(location);
// 判断是否存在
if (relativeResource.exists()) {
// 加载 relativeResource 中的 BeanDefinition 们
importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
// 添加到actualResources 中
actualResources.add(relativeResource);
}
// 不存在
else {
// 获取根路径
String baseLocation = getReaderContext().getResource().getURL().toString();
// 添加配置文件地址的 Resource 到 actualResources 中,并加载相应的 BeanDefinition 们
// 计算绝对路径,按照绝对路径地址进行操作
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));
}
判断路径
- 相对路径
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
// 获得资源读取器
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 {
// 获得 Resource 对象,
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
// 加载 BeanDefinition 集合
int count = loadBeanDefinitions(resource);
if (actualResources != null) {
// 添加到 actualResources 中
actualResources.add(resource);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
}
return count;
}
}
- 绝对路径
则会根据相应的 Resource 计算出相应的相对路径的 Resource 对象
- Resource 存在,则调用
XmlBeanDefinitionReader#loadBeanDefinitions()
方法- 否则,构造一个绝对
location