对象
ResourceLoader继承对象.pngDefaultResourceLoader目的
{@link ResourceLoader}接口的默认实现。由{@link ResourceEditor}使用,并作为{@link org.springframework.context.support.AbstractApplicationContext}的基类。也可以单独使用。
如果位置值是URL,则返回{@link UrlResource};如果是非URL路径或“classpath:”伪URL,则返回{@link ClassPathResource}。
构造函数
//设置默认ClassLoder
public DefaultResourceLoader() {
this.classLoader = ClassUtils.getDefaultClassLoader();
}
public DefaultResourceLoader(@Nullable ClassLoader classLoader) {
this.classLoader = classLoader;
}
//..setClassLoader、getClassLoader方法
我们可以看到构造函数的主要目的就是赋值classLoader
protocolResolvers
//添加protocolResolvers
public void addProtocolResolver(ProtocolResolver resolver) {
Assert.notNull(resolver, "ProtocolResolver must not be null");
this.protocolResolvers.add(resolver);
}
//获取
public Collection<ProtocolResolver> getProtocolResolvers() {
return this.protocolResolvers;
}
//调用核心方法
@Override
public Resource getResource(String location) {
//我们看到,相当于一个拦截器,优先执行查找resource,找到即返回
for (ProtocolResolver protocolResolver : this.protocolResolvers) {
Resource resource = protocolResolver.resolve(location, this);
if (resource != null) {
return resource;
}
}
//后续代码,不考虑拦截流程。
if (location.startsWith("/")) {
return getResourceByPath(location);
}
else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
}
else {
try {
// Try to parse the location as a URL...
URL url = new URL(location);
return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
}
catch (MalformedURLException ex) {
// No URL -> resolve as resource path.
return getResourceByPath(location);
}
}
}
我们可以看到protocolResolvers,相当于对默认实现的一个增强,传入其他解析查找模式,如果匹配则返回。
默认查找方式主要分为三种
1.匹配开头斜杠和异常。getResourceByPath
2.匹配格式classpath:。ClassPathResource
3.尝试用FileUrlResource或者UrlResource获取
首先我们来分析第一种情况
getResourceByPath
protected Resource getResourceByPath(String path) {
return new ClassPathContextResource(path, getClassLoader());
}
/**
* 通过实现ContextResource接口显式表达上下文相关路径的ClassPathResource,此方法重点在于实现ContextResource
*/
protected static class ClassPathContextResource extends ClassPathResource implements ContextResource {
//基于父类构造
public ClassPathContextResource(String path, @Nullable ClassLoader classLoader) {
super(path, classLoader);
}
@Override
public String getPathWithinContext() {
return getPath();
}
//基于当前路径的重新构建对象
@Override
public Resource createRelative(String relativePath) {
String pathToUse = StringUtils.applyRelativePath(getPath(), relativePath);
return new ClassPathContextResource(pathToUse, getClassLoader());
}
}
我们可以看到getResourceByPath,可以简单的看做对ClassPathResource 的增强。即调用ClassPathResource 进行解析。
ClassPathResource解析,查看第五节
从上可以看出,第一种情况和第二种情况都是调用ClassPathResource 实现
总结
DefaultResourceLoader功能有2:
1.增加基于protocolResolvers的拦截增强
2.基于ClassPathResource 、FileUrlResource、UrlResource解析,优先级从左到右
网友评论