相关源码注释
ApplicationContext
Spring 5 DefaultResourceLoader 源码注释
Spring 5 AbstractApplicationContext 源码注释
BeanFactory
Spring 5 SimpleAliasRegistry 源码注释
Spring 5 DefaultSingletonBeanRegistry 源码注释
Spring 5 FactoryBeanRegistrySupport 源码注释
Spring 5 AbstractBeanFactory 源码注释
Spring 5 AbstractAutowireCapableBeanFactory 源码注释
Spring 5 DefaultLisbaleBeanFactory 源码注释
UML类图
源码
/**
* Default implementation of the {@link ResourceLoader} interface.
* Used by {@link ResourceEditor}, and serves as base class for
* {@link org.springframework.context.support.AbstractApplicationContext}.
* Can also be used standalone.
* <p>
* {@link ResourceLoader}接口的默认实现。
* 由{@link ResourceEditor}使用,并看作{@link org.springframework.context.support.AbstractApplicationContext}.
* 的基类。也可以独立使用。
* </p>
* <p>Will return a {@link UrlResource} if the location value is a URL,
* and a {@link ClassPathResource} if it is a non-URL path or a
* "classpath:" pseudo-URL.
* <p>
* 如位置值是一个URL,会返回一个 {@link UrlResource}对象,
* 如果是非URL路径或者是一个'classpatch:'伪路径,会返回一个 {@link ClassPathResource}
* 对象
* </p>
*
* @author Juergen Hoeller
* @since 10.03.2004
* @see FileSystemResourceLoader
* @see org.springframework.context.support.ClassPathXmlApplicationContext
*/
public class DefaultResourceLoader implements ResourceLoader {
/**
* 类加载器
*/
@Nullable
private ClassLoader classLoader;
/**
* 协议解析器组
*/
private final Set<ProtocolResolver> protocolResolvers = new LinkedHashSet<>(4);
/**
* 资源映射缓存
*/
private final Map<Class<?>, Map<Resource, ?>> resourceCaches = new ConcurrentHashMap<>(4);
/**
* Create a new DefaultResourceLoader.
* <p>创建一个新的DefaultResourceLoader</p>
* <p>ClassLoader access will happen using the thread context class loader
* at the time of this ResourceLoader's initialization.
* <p>
* 在这个ResourceLoader初始化期间,将使用线程上下文加载器进行Classload进行访问
* </p>
* @see java.lang.Thread#getContextClassLoader()
*/
public DefaultResourceLoader() {
// 获取默认类加载器,一般返回线程上下文类加载器,没有就返回加载ClassUtils的类加载器,
// 还是没有就返回系统类加载器,最后还是没有就返回null
this.classLoader = ClassUtils.getDefaultClassLoader();
}
/**
* Create a new DefaultResourceLoader.
* <p>创建一个新的DefaultResourceLoader</p>
* @param classLoader the ClassLoader to load class path resources with, or {@code null}
* for using the thread context class loader at the time of actual resource access
* -- ClassLoader用来加载类路径资源,或用于实际资源访问时,使用线程上下文加载器
* 返回null
*/
public DefaultResourceLoader(@Nullable ClassLoader classLoader) {
this.classLoader = classLoader;
}
/**
* Specify the ClassLoader to load class path resources with, or {@code null}
* for using the thread context class loader at the time of actual resource access.
* <p>
* 指定ClassLoader以加载类路径资源,或者用于实际资源访问时,使用线程上下文加载器
* 返回null
* </p>
* <p>The default is that ClassLoader access will happen using the thread context
* class loader at the time of this ResourceLoader's initialization.
* <p>
* 默认情况下,在ResourceLoader初始化期间,将使用线程上下文类加载器进行ClassLoader
* 访问
* </p>
*/
public void setClassLoader(@Nullable ClassLoader classLoader) {
this.classLoader = classLoader;
}
/**
* Return the ClassLoader to load class path resources with.
* <p>返回指定ClassLoader以加载类路径资源</p>
* <p>Will get passed to ClassPathResource's constructor for all
* ClassPathResource objects created by this resource loader.
* <p>将这个资源加载器创建的所有ClassPathResource对象传递给ClassPathResource的构造器
* </p>
* @see ClassPathResource
*/
@Override
@Nullable
public ClassLoader getClassLoader() {
//如果classLoader不为null就直接返回class,否则使用默认的类加载器
return (this.classLoader != null ? this.classLoader : ClassUtils.getDefaultClassLoader());
}
/**
* Register the given resolver with this resource loader, allowing for
* additional protocols to be handled.
* <p>
* 向这个资源加载器注册给定的解析器,运行处理额外协议
* </p>
* <p>Any such resolver will be invoked ahead of this loader's standard
* resolution rules. It may therefore also override any default rules.
* <p>
* 任何此类解析器都将在这个加载器的标准解析规则之前调用。因此,它也可以覆盖任何
* 默认规则。
* </p>
* @since 4.3
* @see #getProtocolResolvers()
*/
public void addProtocolResolver(ProtocolResolver resolver) {
//如果resolver为null,抛出异常
Assert.notNull(resolver, "ProtocolResolver must not be null");
//将resolver添加到protocalResolvers中
this.protocolResolvers.add(resolver);
}
/**
* Return the collection of currently registered protocol resolvers,
* allowing for introspection as well as modification.
* <p>
* 返回当前已注册的协议解析器列表,允许自省和修改
* </p>
* @since 4.3
*/
public Collection<ProtocolResolver> getProtocolResolvers() {
return this.protocolResolvers;
}
/**
* Obtain a cache for the given value type, keyed by {@link Resource}.
* 获取给定值类型的缓存,以{@link Resource}作为键名
* @param valueType the value type, e.g. an ASM {@code MetadataReader}
* -- 值类型,例如ASM{@code MetaDataReader}
* @return the cache {@link Map}, shared at the {@code ResourceLoader} level
* -- 缓存{@link Map},在{@code ResourceLoader}级别共享
* @since 5.0
*/
@SuppressWarnings("unchecked")
public <T> Map<Resource, T> getResourceCache(Class<T> valueType) {
//如果从resourceCache中获取valueType对应的值,如果不存在,就新建一个返回出去
//ConcurrentHashMap:可以将其当做HashMap使用,区别在于ConcurrentHashMap是线程安全的;
// ConcurrentHashMap在对象中保存了一个Segment数组,即将整个Hash表划分为多个分段;而每个Segment元素,即每个分段则类似于一个Hashtable;
// 这样,在执行put操作时首先根据hash算法定位到元素属于哪个Segment,然后对该Segment加锁即可。因此,ConcurrentHashMap在多线程并
// 发编程中可是实现多线程put操作
return (Map<Resource, T>) this.resourceCaches.computeIfAbsent(valueType, key -> new ConcurrentHashMap<>());
}
/**
* Clear all resource caches in this resource loader.
* <p>
* 清空在资源加载器中的所有资源缓存
* </p>
* @since 5.0
* @see #getResourceCache
*/
public void clearResourceCaches() {
//清空resourceCaches
this.resourceCaches.clear();
}
@Override
public Resource getResource(String location) {
//如果location为null,抛出异常
Assert.notNull(location, "Location must not be null");
//遍历所有协议解析器
for (ProtocolResolver protocolResolver : getProtocolResolvers()) {
//如果protocolResolver的协议匹配,根据defaultResourceLoader解析location
Resource resource = protocolResolver.resolve(location, this);
//如果资源对象不为null
if (resource != null) {
//返回该资源对象
return resource;
}
}
//如果localion是以'/'开头
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);
}
}
}
/**
* Return a Resource handle for the resource at the given path.
* <p>返回给定路径下资源的资源句柄</p>
* <p>The default implementation supports class path locations. This should
* be appropriate for standalone implementations but can be overridden,
* e.g. for implementations targeted at a Servlet container.
* <p>默认实现支持类路径位置。这个应该适用于独立的实现但可以被复写,例如针对Servlet容器的实现</p>
* @param path the path to the resource 资源路径
* @return the corresponding Resource handle 对应的资源句柄
* @see ClassPathResource
* @see org.springframework.context.support.FileSystemXmlApplicationContext#getResourceByPath
* @see org.springframework.web.context.support.XmlWebApplicationContext#getResourceByPath
*/
protected Resource getResourceByPath(String path) {
return new ClassPathContextResource(path, getClassLoader());
}
/**
* ClassPathResource that explicitly expresses a context-relative path
* through implementing the ContextResource interface.
* <p>
* 通过实现ContextResource接口显示表示上下文相对路径的ClasPathResource
* </p>
*/
protected static class ClassPathContextResource extends ClassPathResource implements ContextResource {
/**
* 使用ClassLoader为path创建一个新的ClassPathContextResource.
* 前导斜杆将被删除, 因为ClassLoader资源访问方法不接受它。
* @param path 资源路径
* @param classLoader 类加载器
*/
public ClassPathContextResource(String path, @Nullable ClassLoader classLoader) {
super(path, classLoader);
}
@Override
public String getPathWithinContext() {
//返回此资源的路径(作为类路径中的资源路径)
return getPath();
}
@Override
public Resource createRelative(String relativePath) {
//将给定相对路径应用于给定Java资源路径,组装成完整路径
String pathToUse = StringUtils.applyRelativePath(getPath(), relativePath);
// 使用ClassLoader为path创建一个新的ClassPathContextResource.
// 前导斜杆将被删除, 因为ClassLoader资源访问方法不接受它。
return new ClassPathContextResource(pathToUse, getClassLoader());
}
}
}
ClassPathResource
版权声明:本文为qq_30321211原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。