在日常程序开发中,处理外部资源是很繁琐的事情,在上一篇文章里面我们已经介绍了有关资源定义的问题,那么如何加载这些资源呢。spring定义了不同的加载Resource的加载策略,主要用来返回一个Resource对象,说白了,你可以把他看做Resource的一个工厂。我们先来分析下。
1.ResourceLoader 类,这是定义资源加载策略的顶层接口,主要有两个方法。有两个直接的实现类:DefaultResourceLoader,ResourcePatternResolver
package com.wang.spring.beans.resourceLoader; import com.wang.spring.beans.resource.Resource; /** * @author wxe * @since 1.0.0 */ public interface ResourceLoader { public static final String CLASSPATH_URL_PREFIX = "classpath:"; /** * 获取资源 * @param location * @return */ Resource getResource(String location); /** * 获取ClassLoader * @return */ ClassLoader getClassLoader(); }
2.DefaultResourceLoader类,这个是spring提供的默认ResourceLoader.其中根据location可以返回ClasPathResource、UrlResource实例等。ResourceLoader在进行加载资源时需要根据location的前缀来判断到底该返回哪种Resource.主要是判断:1)如果location以"/"开始的路径,则根据DefaultResourceLoader直接返回ClassPathContextResource,这个内部静态类getResourceByPath()方法默认返回ClassPathContextResource实例,在FileSystemResourceLoader中有不同实现。3)如果不是这两种情况,则返回URLResource.但是如果是以类似resources/META-INF/MENIFEST.MF的相对路径,创建URL的时候,会抛出异常,这个时候则返回ClassPathContextResource。
package com.wang.spring.beans.resourceLoader; import java.net.MalformedURLException; import java.net.URL; import com.wang.spring.beans.resource.ClassPathResource; import com.wang.spring.beans.resource.ContextResource; import com.wang.spring.beans.resource.Resource; import com.wang.spring.utils.ClassUtils; /** * 默认资源加载,可以返回ClassPathResource、UrlResource * @author wxe * @since 1.0.0 */ public class DefaultResourceLoader implements ResourceLoader { private ClassLoader classLoader; /** * 使用前缀来判断需要加载返回什么类型的Resource,“classpath:path”表示返回ClasspathResource,“http://path”和“file:path”表示返回UrlResource资源 * 如果没有添加前缀 */ @Override public Resource getResource(String location) { //如果以"/"开头,则根据path判断,返回ClassPathContextResource if (location.startsWith("/")) { return getResourceByPath(location); } //如果以"classpath:"开头,则返回ClassPathResource,并且传入的path需要截取掉classpath:前缀 if (location.startsWith(CLASSPATH_URL_PREFIX)) { return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader()); } else { try { URL url = new URL(location); return new UrlResource(url); } catch (MalformedURLException e) { //创建不成功,根据path返回Resource return getResourceByPath(location); } } } /** * 根据路径获取Resource * @param path * @return */ protected Resource getResourceByPath(String path) { return new ClassPathContextResource(path, getClassLoader()); } @Override public ClassLoader getClassLoader() { return (this.classLoader != null ? this.classLoader : ClassUtils.getDefaultClassLoader()); } /** * * @author wxe * @since 1.0.0 */ protected static class ClassPathContextResource extends ClassPathResource implements ContextResource { public ClassPathContextResource(String path, 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()); } } }
3.ResourcePatternResolver,这个接口只有一个方法,就是getResources()但是,这里与之前返回的不一样,返回的是一个Resouce数组,也就是说这个接口可以返回多个Resource。这个接口主要是为了适应ant风格路径而准备的。ANT通配符有三种: * ——匹配0或者任意数量的字符。比如URL路径为:classpath*:applicationContext-*.xml,表示在所有以classpath开始的路径中,所有以applicationContext-开始的xml文件。
?——匹配任何单字符,比如URL路径为:classpath:applicationContext-*.xml,表示在classpath路径下,任何以applicationContext-开始的xml文件。比如classpath:applicationContext-A.xml可以匹配到,但是classpath:applicationContext-AA.xml无法匹配。
**——匹配0或者更多的目录,比如URL路径为:“cn/**/config.xml”表示在任何cn目录下,任何子目录中的config.xml文件。将匹配“cn /config.xml”,也匹配“cn/javass/spring/config.xml”。
package com.wang.spring.beans.resourceLoader; import java.io.IOException; import com.wang.spring.beans.resource.Resource; /** *用于匹配"classpath*:"的路径,获取多个Resource,简化路径配置的定义 * @author wxe * @since 1.0.0 */ public interface ResourcePatternResolver extends ResourceLoader { String CLASSPATH_ALL_URL_PREFIX = "classpath*:"; /** * 返回多个Resource * @param locationPattern * @return * @throws IOException */ Resource[] getResources(String locationPattern) throws IOException; }
4.
我们只看继承,然后重写getResource()的方法。
@Override public Resource[] getResources(String locationPattern) throws IOException { return this.resourcePatternResolver.getResources(locationPattern); }
posted on
浙公网安备 33010602011771号