The difference between classpath*: and classpath: when Spring loads resources

from : http://blog.csdn.net/kkdelta/article/details/5507799

 

 

Spring can load files from classpath by specifying classpath*: and classpath: prefix plus path, such as bean definition files. The appearance of classpath*: is to load the same file from multiple jar files. classpath: can only be loaded and found the first file of .

For example, the package 'com.test.rs' in resource1.jar has a 'jarAppcontext.xml' file with the following contents:

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

The package 'com.test.rs' in resource2.jar also has a 'jarAppcontext.xml' file with the following contents:

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

By using the following code, the files in both jar packages can be loaded in

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

And if you write the following code, you can only find one of the xml files (the order depends on the loading order of the jar package)

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

The use of classpath*: is for the parallel development of multiple components (eventually released into different jar packages), and the respective bean definition files follow certain rules: package+filename, and callers who use these components can load these files in. .

The loading of classpath*: uses the classloader  getResources() method. If it is running on a different J2EE server, since the application server provides its own classloader implementation, their behavior when processing jar files may be different. To test classpath*: whether it works, you can use the classloader to load the file from the jar file in the classpath to test: getClass().getClassLoader().getResources("<someFileInsideTheJar>"). (The above example is the state running in sun's jre)

 From Spring's source code, in the PathMatchingResourcePatternResolver class, we can understand its handling more clearly: if it starts with classpath*, it will traverse the 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()]);  
  13. }  

http://blog.csdn.net/kkdelta/article/details/5560210, which introduces all files with names found in traversing the classpath in JAVA.

 

In addition, when loading resources, the meanings of other prefixes are shown in the following table: Note that classpath* can only be used with the path of the specified configuration file, and cannot be used in the parameters used for getResource. For example, appContext.getResource("classpath*:conf/bfactoryCtx .xml") will be abnormal.

 

Prefix example description

classpath:

classpath:com/myapp/config.xml

Load from classpath.

file:

file:/data/config.xml

as  URL loaded from the filesystem.

http:

http://myserver/logo.png

as  URL loaded.

(none)

/data/config.xml

Judge according  ApplicationContext to.

The reason can be seen from Spring's source code: if it is classpath: at the beginning, load from classpath, otherwise try the URL, if it fails, call 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.     }  


getResourceByPath会被不同ApplicationContext 实现覆盖.

如 GenericWebApplicationContext覆盖为如下:

 
  1. protected Resource getResourceByPath(String path) {  
  2.         return new 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.         return new FileSystemResource(path);  
  12.     }  

最终从文件加载的时候仍然是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.     }  

如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;  
  7. }  

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327002219&siteId=291194637