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.
- 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, 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.
classpath: |
|
Load from classpath. |
file: |
|
|
http: |
|
as |
(none) |
|
Judge according |
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
- public Resource getResource(String location) {
- Assert.notNull(location, "Location must not be null");
- if (location.startsWith(CLASSPATH_URL_PREFIX)) {
- returnnew ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
- }
- else {
- try {
- // Try to parse the location as a URL...
- URL url = new URL(location);
- returnnew 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);
}
如ServletContextResource得到inputstream的方法是利用servletContext.getResourceAsStream.
- public InputStream getInputStream() throws IOException {
- InputStream is = this.servletContext.getResourceAsStream(this.path);
- if (is == null) {
- thrownew FileNotFoundException("Could not open " + getDescription());
- }
- return is;
- }