Spring加载resource时classpath*:与classpath:的区别

Spring加载resource时classpath*:与classpath:的区别Spring 可以通过指定 classpath 与 classpath 前缀加路径的方式从 classpath 加载文件 如 bean 的定义文件 classpath 的出现是为了从多个 jar 文件中加载相同的文件 classpath 只能加载找到的第一个文件 比如 resource1 jar 中的 package com test rs 有一个 jarAppcontex xml 文件 内容如下

大家好,又见面了,我是你们的朋友全栈君。
如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Spring可以通过指定classpath*:与classpath:前缀加路径的方式从classpath加载文件,如bean的定义文件.classpath*:的出现是为了从多个jar文件中加载相同的文件.classpath:只能加载找到的第一个文件.

比如 resource1.jar中的package ‘com.test.rs’ 有一个 ‘jarAppcontext.xml’ 文件,内容如下:

<bean name=”ProcessorImplA” class=”com.test.spring.di.ProcessorImplA” />

resource2.jar中的package ‘com.test.rs’ 也有一个 ‘jarAppcontext.xml’ 文件,内容如下:

<bean id=”ProcessorImplB” class=”com.test.spring.di.ProcessorImplB” />

通过使用下面的代码则可以将两个jar包中的文件都加载进来

ApplicationContext ctx = new ClassPathXmlApplicationContext( “classpath*:com/test/rs/jarAppcontext.xml”);

而如果写成下面的代码,就只能找到其中的一个xml文件(顺序取决于jar包的加载顺序)

ApplicationContext ctx = new ClassPathXmlApplicationContext( “classpath:com/test/rs/jarAppcontext.xml”);

classpath*:的加载使用了classloader的 getResources() 方法,如果是在不同的J2EE服务器上运行,由于应用服务器提供自己的classloader实现,它们在处理jar文件时的行为也许会有所不同。 要测试classpath*: 是否有效,可以用classloader从classpath中的jar文件里加载文件来进行测试:getClass().getClassLoader().getResources("<someFileInsideTheJar>")。(上面的例子是在sun的jre中运行的状态)

 从Spring的源码,在PathMatchingResourcePatternResolver类中,我们可以更清楚的了解其对的处理:如果是以classpath*开头,它会遍历classpath.

 protected Resource[] findAllClassPathResources(String location) throws IOException { String path = location; if (path.startsWith("/")) { path = path.substring(1); } Enumeration resourceUrls = getClassLoader().getResources(path); Set<Resource> result = new LinkedHashSet<Resource>(16); while (resourceUrls.hasMoreElements()) { URL url = (URL) resourceUrls.nextElement(); result.add(convertClassLoaderURL(url)); } return result.toArray(new Resource[result.size()]); }

http://blog.csdn.net/kkdelta/article/details/,简介了在JAVA里遍历classpath中读取找到的所有符合名称的文件.

前缀 例子 说明

classpath:

classpath:com/myapp/config.xml

从classpath中加载。

file:

file:/data/config.xml

作为 URL 从文件系统中加载。

http:

http://myserver/logo.png

作为 URL 加载。

(none)

/data/config.xml

根据 ApplicationContext 进行判断。

从Spring的源码可以看出原因:如果是classpath:开头,从classpath加载,否则尝试URL,如果失败,调用 getResourceByPath

public Resource getResource(String location) { Assert.notNull(location, "Location must not be null"); 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 new UrlResource(url); } catch (MalformedURLException ex) { // No URL -> resolve as resource path. return getResourceByPath(location); } } }

getResourceByPath会被不同 ApplicationContext 实现覆盖.

如 GenericWebApplicationContext覆盖为如下:

protected Resource getResourceByPath(String path) { return new ServletContextResource(this.servletContext, path); } 如 FileSystemXmlApplicationContext覆盖为如下: protected Resource getResourceByPath(String path) { if (path != null && path.startsWith("/")) { path = path.substring(1); } return new FileSystemResource(path); }

最终从文件加载的时候仍然是JAVA中常见的读取文件的方法:

如ClassPathResource得到inputstream的方法是利用class loader.

 public InputStream getInputStream() throws IOException { InputStream is; if (this.clazz != null) { is = this.clazz.getResourceAsStream(this.path); }

如FileSystemResource得到inputstream的方法是利用FileInputStream.

    public InputStream getInputStream() throws IOException {

        return new FileInputStream(this.file);
    }

 public InputStream getInputStream() throws IOException { InputStream is = this.servletContext.getResourceAsStream(this.path); if (is == null) { throw new FileNotFoundException("Could not open " + getDescription()); } return is; }

注意:
用classpath*:需要遍历所有的classpath,所以加载效率会比较差一些,如果只使用classpath:,需要规划好资源文件的路径,尽量避免重名,导致资源文件加载不到的问题。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/234042.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • pcharm激活码_通用破解码

    pcharm激活码_通用破解码,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月16日
    68
  • Keras/Tensorflow+python+yolo3训练自己的数据集

    Keras/Tensorflow+python+yolo3训练自己的数据集代码:https://github.com/qqwweee/keras-yolo3修改yolov3.cfg文件:https://blog.csdn.net/lilai619/article/details/79695109本文介绍如何制作数据集、修改代码、不加载预权重从头跑自己的训练数据一、简单回顾一下yolo原理:   1、端到端,输入图像,一次性输出每个栅格预测的一种或多种物体   2、坐…

    2022年6月29日
    30
  • kettle基础教程-kettle9教程「建议收藏」

    kettle基础教程-kettle9教程「建议收藏」一.安装部署1.JDK1.8安装及环境变量的配置https://blog.csdn.net/weixin_39549656/article/details/795406442.kettle9安装与启动kettle下载目录:https://sourceforge.net/projects/pentaho/files/kettle9.2下载地址:https://sourceforge.net/projects/pentaho/files/Pentaho-9.2/client-tool

    2022年5月23日
    35
  • Teamviewer无法连接,日志报错error 10049「建议收藏」

    Teamviewer无法连接,日志报错error 10049「建议收藏」Teamviewer无法连接,一直处于”Notready.Pleasecheckyourconnection”状态,无法获取到连接ID,也无法通过ID连接Partner,但是电脑的网路连接正常(网页能上,各种网络应用程序都可以使用),并且FireWall都处于off状态.查看teamveiwer的程序日志(从Extral->Openlogfile可以打开)后,报Error10049

    2022年10月1日
    3
  • js和html全局变量,JavaScript全局变量与局部变量

    js和html全局变量,JavaScript全局变量与局部变量原文:深入理解JavaScript的变量作用域在学习JavaScript的变量作用域之前,我们应当明确几点:JavaScript的变量作用域是基于其特有的作用域链的。JavaScript没有块级作用域。函数中声明的变量在整个函数中都有定义。1、JavaScript的作用域链首先看下下面这段代码:varrain=1;functionrainman(){varman=2;function…

    2022年6月12日
    33

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号