Spring 5 DefaultResourceLoader 源码注释

  • Post author:
  • Post category:其他




相关源码注释



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类图

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


Spring 5 Resource 源码注释



版权声明:本文为qq_30321211原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。