• Spring IOC之资源加载器


    ResourceLoader资源加载器

    ResourceLoader作为 Spring 统一的资源加载器 ,我们来看一下它的ULM图

    在这里插入图片描述

    ResourceLoader 接口提供两个方法:`getResource()、getClassLoader()。

    getResource(String location)方法,可以根据一个资源地址加载资源文件,资源地址的表达式可以是以下几种:

    • classpath:前缀开头的表达式,例如: classpath:xxx.xml
    • “/”开头的表达式,例如:/WEB-INF/classes/xxx.xml
    • 非“/”开头的表达,例如:WEB-INF/classes/xxx.xml
    • url协议,例如:file:/D:/workspace/idea/xxx/target/classes/xxx.xml

    该方法的主要实现是在其子类 DefaultResourceLoader 中实现,具体过程我们在分析 DefaultResourceLoader 时做详细说明。 (注意,该方法不支持解析ant风格的资源路径表达式。

    Ant风格,为请求路径的一种匹配方式。

    ANT通配符有三种:

    通配符说明
    ?匹配任何单字符
    *匹配0或者任意数量的字符
    **匹配0或者更多的目录

    getClassLoader() 返回 ClassLoader 实例,对于想要获取 ResourceLoader 使用的 ClassLoader 用户来说,可以直接调用该方法来获取

    DefaultResourceLoader

    DefaultResourceLoader 是 ResourceLoader 的默认实现。ResourceLoader 中最核心的方法为 getResource(),它根据提供的 location 返回相应的 Resource,而 DefaultResourceLoader 对该方法提供了核心实现(它的其它子类都没有提供覆盖该方法,所以可以断定ResourceLoader 的资源加载策略就封装 DefaultResourceLoader中)

    	//获取Resource的具体实现类实例
    	@Override
    	public Resource getResource(String location) {
    		Assert.notNull(location, "Location must not be null");
    		//ProtocolResolver ,用户自定义协议资源解决策略
    		for (ProtocolResolver protocolResolver : getProtocolResolvers()) {
    			Resource resource = protocolResolver.resolve(location, this);
    			if (resource != null) {
    				return resource;
    			}
    		}
    		//如果是以/开头,则构造ClassPathContextResource返回
    		if (location.startsWith("/")) {
    			return getResourceByPath(location);
    		}
    		//若以classpath:开头,则构造 ClassPathResource 类型资源并返回,在构造该资源时,
    		// 通过 getClassLoader()获取当前的 ClassLoader
    		else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
    			return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
    		}
    		else {
    			//构造 URL ,尝试通过它进行资源定位,若没有抛出 MalformedURLException 异常,
    			// 则判断是否为 FileURL , 如果是则构造 FileUrlResource 类型资源,否则构造 UrlResource。
    			// 若在加载过程中抛出 MalformedURLException 异常,
    			// 则委派 getResourceByPath() 实现资源定位加载
    			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);
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 带classpath前缀的写法更易于移植,相对于一般的java程序,classpath指向的是类文件存放的位置,而对于web应用来说,classpath指向的是WEB-INF/classes,因此classpath: 的写法还有屏蔽不同应用类型的作用,实际开发中也以classpath:前缀的写法居多
    • DefaultResourceLoader的getResource(String location)可以看作为是一个模板方法,getResourceByPath(String path) 是钩子函数(FileSystemResourceLoader主要就是重写了这个方法),只不过DefaultResourceLoader自身也为其提供了实现,

    FileSystemResourceLoader

    FileSystemResourceLoader, 它继承 DefaultResourceLoader 且覆写了 getResourceByPath(String),使之从文件系统加载资源并以 FileSystemResource 类型返回。能够更加精确的判断FileSystemResource文件类型资源

    public class FileSystemResourceLoader extends DefaultResourceLoader {
    
    	/**
    	 * Resolve resource paths as file system paths.
    	 * 

    Note: Even if a given path starts with a slash, it will get * interpreted as relative to the current VM working directory. * @param path the path to the resource * @return the corresponding Resource handle * @see FileSystemResource * @see org.springframework.web.context.support.ServletContextResourceLoader#getResourceByPath */ @Override protected Resource getResourceByPath(String path) { if (path.startsWith("/")) { path = path.substring(1); } return new FileSystemContextResource(path); } /** * FileSystemResource that explicitly expresses a context-relative path * through implementing the ContextResource interface. */ private static class FileSystemContextResource extends FileSystemResource implements ContextResource { public FileSystemContextResource(String path) { super(path); } @Override public String getPathWithinContext() { return getPath(); } } }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    ClassRelativeResourceLoader

    ClassRelativeResourceLoader继承自DefaultResourceLoader,并重写了getResourceByPath(String path) 。

    ClassRelativeResourceLoader返回的是ClassRelativeContextResource对象,ClassRelativeContextResource对象表示上下文相对路径 .

    例如包结构:

    com.bushro.web
             LoginController
             test.xml
    
    • 1
    • 2
    • 3

    如果需要加载test.xml文件,咱们就可以在LoginController这么写:

    	public String loginPage() throws IOException {
    		ResourceLoader resourceLoader=new ClassRelativeResourceLoader(this.getClass());
    		Resource resource=resourceLoader.getResource("test.xml");
    		System.out.println(resource.getFile().getPath());
    		return "index";
    	}  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    ServletContextResourceLoader

    该类的扩展功能是可以从Servlet上下文的根目录加载资源。

    ResourcePatternResolver

    • ResourcePatternResolver扩展了ResourceLoader可以返回多个资源文件,同时也新增了一种新的协议前缀 classpath*:,该协议前缀由其子类负责实现。
    • 这个接口是Spring提供的解析 Ant 表达式的接口,定义了解析Ant表达式的方法(上面有说明Ano表达式),PathMatchingResourcePatternResolver实现了这个接口
    public interface ResourcePatternResolver extends ResourceLoader {
    
        /**
         * 在所有根目录下搜索文件的伪URL的前缀
         * 与ResourceLoader中classpath不同的地方在于,此前缀会在所有的JAR包的根目录下搜索指定文件。
         */
        String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
    
        /**
         * 返回指定路径下所有的资源对象。
         * 返回的对象集合应该有Set的语义,也就是说,对于同一个资源,只应该返回一个资源对象
         */
        Resource[] getResources(String locationPattern) throws IOException;
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    WebGL学习(一)渲染关系
    Chapter6.3:线性系统的校正方法考研参考题
    【大数据入门核心技术-Zookeeper】(五)ZooKeeper集群搭建
    内外“双驱”, NFT价值UPUP
    selenium4 元素定位
    Jsp 学习笔记
    算法专题:双指针
    强化学习 补充笔记(TD算法、Q学习算法、SARSA算法、多步TD目标、经验回放、高估问题、对决网络、噪声网络)
    java:观察者模式
    数据结构与算法训练:第二十七、二十八弹
  • 原文地址:https://blog.csdn.net/BushQiang/article/details/126293238