Spring加載resource時classpath*:與classpath:的區別

Spring能夠經過指定classpath*:與classpath:前綴加路徑的方式從classpath加載文件,如bean的定義文件.classpath*:的出現是爲了從多個jar文件中加載相同的文件.classpath:只能加載找到的第一個文件.java

好比 resource1.jar中的package 'com.test.rs' 有一個 'jarAppcontext.xml' 文件,內容以下:spring

<bean name="ProcessorImplA" class="com.test.spring.di.ProcessorImplA" />服務器

resource2.jar中的package 'com.test.rs' 也有一個 'jarAppcontext.xml' 文件,內容以下:app

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

經過使用下面的代碼則能夠將兩個jar包中的文件都加載進來測試

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

而若是寫成下面的代碼,就只能找到其中的一個xml文件(順序取決於jar包的加載順序)url

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

classpath*:的使用是爲了多個component(最終發佈成不一樣的jar包)並行開發,各自的bean定義文件按照必定的規則:package+filename,而使用這些component的調用者能夠把這些文件都加載進來..net

classpath*:的加載使用了classloader的 getResources() 方法,若是是在不一樣的J2EE服務器上運行,因爲應用服務器提供本身的classloader實現,它們在處理jar文件時的行爲也許會有所不一樣。 要測試classpath*: 是否有效,能夠用classloader從classpath中的jar文件里加載文件來進行測試:getClass().getClassLoader().getResources("<someFileInsideTheJar>")。(上面的例子是在sun的jre中運行的狀態)

從Spring的源碼,在PathMatchingResourcePatternResolver類中,咱們能夠更清楚的瞭解其對的處理:若是是以classpath*開頭,它會遍歷classpath.

  1. protected Resource[] findAllClassPathResources(String location) throws IOException { 
  2.     String path = location; 
  3.     if (path.startsWith("/")) { 
  4.         path = path.substring(1); 
  5.     } 
  6.     Enumeration resourceUrls = getClassLoader().getResources(path); 
  7.     Set<Resource> result = new LinkedHashSet<Resource>(16); 
  8.     while (resourceUrls.hasMoreElements()) { 
  9.         URL url = (URL) resourceUrls.nextElement(); 
  10.         result.add(convertClassLoaderURL(url)); 
  11.     } 
  12.     return result.toArray(new Resource[result.size()]); 
    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/5560210,簡介了在JAVA裏遍歷classpath中讀取找到的全部符合名稱的文件.

 

另外在加載resource的時候,其餘前綴的意義以下表所示:注意classpath*只能用與指定配置文件的路徑,不能用在用於getResource的參數.如appContext.getResource("classpath*:conf/bfactoryCtx.xml")會異常的.

 

前綴 例子 說明

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

  1. public Resource getResource(String location) { 
  2.         Assert.notNull(location, "Location must not be null"); 
  3.         if (location.startsWith(CLASSPATH_URL_PREFIX)) { 
  4.             returnnew ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader()); 
  5.         } 
  6.         else
  7.             try
  8.                 // Try to parse the location as a URL...  
  9.                 URL url = new URL(location); 
  10.                 returnnew UrlResource(url); 
  11.             } 
  12.             catch (MalformedURLException ex) { 
  13.                 // No URL -> resolve as resource path.  
  14.                 return getResourceByPath(location); 
  15.             } 
  16.         } 
  17.     } 
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覆蓋爲以下:

  1. protected Resource getResourceByPath(String path) { 
  2.         returnnew ServletContextResource(this.servletContext, path); 
  3.     } 
  4.  
  5. 如 FileSystemXmlApplicationContext覆蓋爲以下: 
  6.  
  7. protected Resource getResourceByPath(String path) { 
  8.         if (path != null && path.startsWith("/")) { 
  9.             path = path.substring(1); 
  10.         } 
  11.         returnnew FileSystemResource(path); 
  12.     } 
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.

  1. public InputStream getInputStream() throws IOException { 
  2.     InputStream is; 
  3.     if (this.clazz != null) { 
  4.         is = this.clazz.getResourceAsStream(this.path); 
  5.     } 
    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);     }

如ServletContextResource獲得inputstream的方法是利用servletContext.getResourceAsStream.

  1. public InputStream getInputStream() throws IOException { 
  2.     InputStream is = this.servletContext.getResourceAsStream(this.path); 
  3.     if (is == null) { 
  4.         thrownew FileNotFoundException("Could not open " + getDescription()); 
  5.     } 
  6.     return is; 
相關文章
相關標籤/搜索