Spring能夠經過指定classpath*:與classpath:前綴加路徑的方式從classpath加載文件,如bean的定義文件.classpath*:的出現是爲了從多個jar文件中加載相同的文件.classpath:只能加載找到的第一個文件.java
好比 resource1.jar中的package 'com.test.rs' 有一個 'jarAppcontext.xml' 文件,內容以下:web
<bean name="ProcessorImplA" class="com.test.spring.di.ProcessorImplA" />spring
resource2.jar中的package 'com.test.rs' 也有一個 'jarAppcontext.xml' 文件,內容以下:服務器
<bean id="ProcessorImplB" class="com.test.spring.di.ProcessorImplB" />app
public InputStream getInputStream() throws IOException { ide
InputStream is = this.servletContext.getResourceAsStream(this.path); oop
if (is == null) { 測試
throw new FileNotFoundException("Could not open " + getDescription()); this
} url
return is;
}
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.
[java] view plain copy
<EMBED id=ZeroClipboardMovie_5 name=ZeroClipboardMovie_5 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=18 width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=5&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
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.
[java] view plain copy
<EMBED id=ZeroClipboardMovie_4 name=ZeroClipboardMovie_4 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=18 width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=4&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
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覆蓋爲以下:
[java] view plain copy
<EMBED id=ZeroClipboardMovie_3 name=ZeroClipboardMovie_3 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=18 width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=3&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
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中加載。 |
file: |
|
|
http: |
|
做爲 |
(none) |
|
根據 |
從Spring的源碼能夠看出緣由:若是是classpath:開頭,從classpath加載,不然嘗試URL,若是失敗,調用 getResourceByPath
[java] view plain copy
<EMBED id=ZeroClipboardMovie_2 name=ZeroClipboardMovie_2 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=18 width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=2&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
經過使用下面的代碼則能夠將兩個jar包中的文件都加載進來
ApplicationContext ctx = new ClassPathXmlApplicationContext( "classpath*:com/test/rs/jarAppcontext.xml");
而若是寫成下面的代碼,就只能找到其中的一個xml文件(順序取決於jar包的加載順序)
ApplicationContext ctx = new ClassPathXmlApplicationContext( "classpath:com/test/rs/jarAppcontext.xml");
classpath*:的使用是爲了多個component(最終發佈成不一樣的jar包)並行開發,各自的bean定義文件按照必定的規則:package+filename,而使用這些component的調用者能夠把這些文件都加載進來.
classpath*:的加載使用了classloader的 getResources()
方法,若是是在不一樣的J2EE服務器上運行,因爲應用服務器提供本身的classloader實現,它們在處理jar文件時的行爲也許會有所不一樣。 要測試classpath*:
是否有效,能夠用classloader從classpath中的jar文件里加載文件來進行測試:getClass().getClassLoader().getResources("<someFileInsideTheJar>")
。(上面的例子是在sun的jre中運行的狀態)
從Spring的源碼,在PathMatchingResourcePatternResolver類中,咱們能夠更清楚的瞭解其對的處理:若是是以classpath*開頭,它會遍歷classpath.
[java] view plain copy
<EMBED id=ZeroClipboardMovie_1 name=ZeroClipboardMovie_1 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=18 width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=1&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">