Spring:資源管理
java 標準資源管理
職責 | 說明 |
---|---|
面向資源 | 檔案系統、artifact(jar、war、ear檔案)以及遠端資源(HTTP、FTP等) |
API整合 | ClassLoader#getResource、java.io.File、java.net.URL |
資源定位 | java.net.URL、java.net.URI |
面向流式儲存 | java.net.URLConnection |
協議擴充套件 | java.net.URLStreamHandler 或 java.net.URLStreamHandlerFactory |
基於java.net.URLStreamHandler
擴充套件協議:jdk1.8內建協議實現,
自定義URLStreamHandler
物件,可以通過以下倆種方式注入到URL中:
- 設定自定義的
URLStreamHandler
類名為Handler
,然後在程式啟動的時候加上-Djava.protocol.handler.pkgs="Handler所在包名"
引數,如果存在多個包名指定,可以通過分隔符"|" - 自定義
java.net.URLStreamHandlerFactory
,然後通過URL#setURLStreamHandlerFactory
設定
具體原理可參考:URL#getURLStreamHandler(String)
方法原始碼
Spring資源管理介面
型別 | 介面 |
---|---|
輸入流 | org.springframework.core.io.InputStreamSource |
只讀資源 | org.springframework.core.io.Resource |
可寫資源 | org.springframework.core.io.WritableResource |
編碼資源 | org.springframework.core.io.support.EncodedResource |
上下文資源 | org.springframework.core.io.ContextResource |
Spring資源載入器
下面列舉了三個常見的資源載入器實現,通過資源載入器載入對應的資源
測試:
public class FileSystemResourceLoaderDemo {
public static void main(String[] args) throws IOException {
String filePath = System.getProperty("user.dir") + "/spring-framework/spring-core/src/main/java/com/wj/resource/FileSystemResourceLoaderDemo.java";
FileSystemResourceLoader resourceLoader = new FileSystemResourceLoader();
Resource resource = resourceLoader.getResource(filePath);
EncodedResource encodedResource = new EncodedResource(resource, "UTF-8");
Reader reader = encodedResource.getReader();
System.out.println(FileCopyUtils.copyToString(reader));
}
}
列印結果:
spring通配路徑資源載入器
通配路徑:
-
org.springframework.core.io.support.ResourcePatternResolver
org.springframework.core.io.support.PathMatchingResourcePatternResolver
路徑匹配器:
-
org.springframework.util.PathMatcher
- Ant模式匹配:
org.springframework.util.AntPathMatcher
- Ant模式匹配:
可以通過通配路徑資源載入器獲取到所有匹配的資源:
示例如下:獲取指定路徑下的所有java檔案
public class ResourcePatternResolverDemo {
public static void main(String[] args) throws IOException {
String filePath = System.getProperty("user.dir") + "/spring-framework/spring-core/src/main/java/com/wj/";
String pattern = "**/*.java";
PathMatchingResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver(new FileSystemResourceLoader());
Resource[] resources = patternResolver.getResources(filePath + pattern);
for (Resource resource : resources) {
System.out.println(resource.getFile().getName());
}
}
}
依賴注入Spring Resource
我在resource下面放了一個屬性配置檔案:
程式碼示例:
@Configuration
public class ResourceInjectDemo {
@Value(ResourceUtils.CLASSPATH_URL_PREFIX + "resource.properties")
private Resource resource;
public Resource getResource() {
return resource;
}
public static void main(String[] args) throws IOException {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ResourceInjectDemo.class);
ResourceInjectDemo demo = applicationContext.getBean(ResourceInjectDemo.class);
EncodedResource encodedResource = new EncodedResource(demo.getResource(), "UTF-8");
Reader reader = encodedResource.getReader();
System.out.println(FileCopyUtils.copyToString(reader));
}
}
這裡通過@Value的形式就可以注入Resource物件到Bean中。
簡單說明一下原理,spring通過
AutowiredAnnotationBeanPostProcessor
後置處理器處理bean中的@Value
註解,獲取到註解的value
值,然後通過TypeConverter
型別轉換器,實際上通過的是ResourceEditor
將String
型別轉換成Resource
,最後通過反射注入。在
ResourceEditor
中使用的就是ResourceLoader
去載入Resource
。
此外,還可以注入陣列型別Resource
:
@Value(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "*.properties")
private Resource[] resources;
原理與前面類似,只不過最後型別轉換使用的是
ResourceArrayPropertyEditor
,而該類中使用的就是前面說到的PathMatchingResourcePatternResolver
去路徑匹配,
關於型別轉換詳細原理可參考我前面的部落格:
ResourceLoader依賴注入
- ResourceLoaderAware回撥
- @Autowired注入ResourceLoader
- 直接注入ApplicationContext,因為ApplicationContext實現了ResourceLoader
示例不就寫了,比較簡單。
原理解釋:
spring容器在啟動的時候,呼叫了prepareBeanFactory方法中,有這麼幾行:
這幾行說明 Spring在依賴注入的時候,當需要注入這四個型別的介面時,會把設定的指定物件注入進去,這裡ResourceLoader指定的物件就是ApplicationContext。
依賴注入的程式碼:
ResourceLoaderAware的原理就更簡單了:主要通過ApplicationContextAwareProcessor後置處理器進行設定,