java用類加載器的5種方式讀取.properties文件
用類加載器的5中形式讀取.properties文件(這個.properties文件一般放在src的下面)
用類加載器進行讀?。哼@里采取先向大家講讀取類加載器的幾種方法;然后寫一個例子把幾種方法融進去,讓大家直觀感受。最后分析原理。(主要是結合所牽涉的方法的源代碼的角度進行分析)
這里先介紹用類加載器讀取的幾種方法:
1.任意類名.class.getResourceAsStream("/文件所在的位置");【文件所在的位置從包名開始寫】
2.和.properties文件在同一個目錄下的類名.class.getResourceAsStream("文件所在的位置");【文件所在的位置從包名開始寫,注意這里和上面的相比較少了一個斜杠/】
當然你也可以寫成跟1一樣的形式即:任意類名.class.getResourceAsStream("/文件所在的位置");
3.任意類名.class.getClassLoader().getResourceAsStream("文件所在的位置");【文件所在的位置從包名開始寫】
4.任意類名.class.getClassLoader().getResource("文件所在的位置").openStream();【文件所在的位置從包名開始寫】
5.任意類名.class.getClassLoader().getResource("文件所在的位置")..openConnection().getInputStream();【文件所在的位置從包名開始寫】
//一個例子,說明上述5中方法的用法。

上面圖片中的各個紅色矩形就是我要讀取的properties文件。主要是兩類。一類直接放在src下面。另一類是放在某個文件夾下面.
//f.properties文件的內(nèi)容如下圖所示;

//上述五種情況說明的代碼如下:
package com.qls.commonclass;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import com.qls.counter.Ok;
/**
* 分別用類加載器的5種方法讀取f.properties文件。
* @author 秦林森
*
*/
public class Test6 {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
/**第一種情形獲取輸入流。
* 任意類名.class.getResourceAsStream("/文件所在的位置");【文件所在的位置從包名開始寫】
* @param args
*/
//獲取輸入流
InputStream in = Test.class.getResourceAsStream("/com/qls/counter/f.properties");
/**
* 第二種情形獲取輸入流。
* 和.properties文件在同一個目錄下的類名.class.getResourceAsStream("文件所在的位置");
* 【文件所在的位置從包名開始寫,注意這里和上面的相比較少了一個斜杠/】
* 這里隨便選擇一個與:f.properties在同一個目錄下的類比如Ok這個類吧!
* 這里你自然也可以寫成跟第一種情況一樣的形式:
* 即:
* InputStream in2 = Ok.class.getResourceAsStream("/com/qls/counter/f.properties");
* 因為第一種情況是針對任意一個類而言的公式。
*/
InputStream in2 = Ok.class.getResourceAsStream("f.properties");
/**
* 第三種情形獲取輸入流:
* 任意類名.class.getClassLoader().getResourceAsStream("文件所在的位置");
* 【文件所在的位置從包名開始寫】
*/
InputStream in3 = Test2.class.getClassLoader().getResourceAsStream("com/qls/counter/f.properties");
/**
* 第四中情形獲取輸入流:
* 任意類名.class.getClassLoader().getResource("文件所在的位置").openStream();
* 【文件所在的位置從包名開始寫】
*/
InputStream in4 = Test4.class.getClassLoader().getResource("com/qls/counter/f.properties").openStream();
/**
* 第五種情形獲取輸入流:
* .任意類名.class.getClassLoader().getResource("文件所在的位置").openConnection().getInputStream();
* 【文件所在的位置從包名開始寫】
*/
InputStream in5 = Test5.class.getClassLoader().getResource("com/qls/counter/f.properties").openConnection().getInputStream();
//創(chuàng)建Properties
Properties prop=new Properties();
//把輸入流in加載到prop中
/*
* 驗證上述5中輸入流是否成立。只需帶入prop.load(InputStream inputStream);驗證即可。
* 也就是:
* prop.load(in);
* prop.load(in2);
* prop.load(in3);
* prop.load(in4);
* prop.load(in5);
*/
prop.load(in5);
System.out.println("sixi="+prop.getProperty("sixi"));
System.out.println("ouyangfeng="+prop.getProperty("ouyangfeng"));
System.out.println("rape="+prop.getProperty("farm"));
}
}/*
Output:
sixi=river
ouyangfeng=masses
farm=flower
**///:~
上述5中方法的原理分析。
首先看看Class中的resolveName(String name)究竟是干什么的。源碼如下所示:
private String resolveName(String name) {
if (name == null) {
return name;
}
if (!name.startsWith("/")) {
Class<?> c = this;
while (c.isArray()) {
c = c.getComponentType();
}
String baseName = c.getName();
int index = baseName.lastIndexOf('.');
if (index != -1) {
name = baseName.substring(0, index).replace('.', '/')
+"/"+name;
}
} else {
name = name.substring(1);
}
return name;
}
下面我把這個源碼講的內(nèi)容翻譯人類語言:
給任意一個字符串name,如果該name是以/開始的,則該函數(shù)返回的是:去掉/這個字符的字符串。(如name="/ouyangfeng" 則調(diào)用該函數(shù)之后得到的結果是:name=ouyangfeng)。
如果該name這個字符串不是以/開始的,則該函數(shù)返回的結果是調(diào)用這個函數(shù)類所在的包名+name組成的字符串(例如假設Test5所在的包名是:com.qls.mount 。則:Test5.class.resolveName("ouyangfeng");返回結果是:com/qls/mount/ouyangfeng)
也就是幫助文檔講述的:
If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
Otherwise, the absolute name is of the following form:modified_package_name/name
Where the modified_package_name is the package name of this object with '/' substituted for '.' ('\u002e').
上述英文我簡要翻譯一下:如果name是以一個/開頭,則這個資源的絕對name就是:name中/之后的部分內(nèi)容。否則:這這個絕對name就是如下形式。包名/name,把這里包名中的.用/代替掉。【如:com.qls.river把.用/代替掉就是:com/qls/river】
然后我們再看看Class類中的getResourceAsStream(String name)的源碼和ClassLoader中的getResourceAsStream(String name)中的源碼。
Class類中的getResourceAsStream(String name)的源碼如下:
public InputStream getResourceAsStream(String name) {
name = resolveName(name);//注意這里有一個resolveName(String name)方法,根據(jù)上述的分析,易知道這個源碼的意思.
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResourceAsStream(name);
}
return cl.getResourceAsStream(name);
}
ClassLoader中的getResourceAsStream(String name)中的源碼如下:
public InputStream getResourceAsStream(String name) {
URL url = getResource(name);
try {
return url != null ? url.openStream() : null;//這句代碼的意思是:如果url不是null時返回的是:url.openStream(),反之如果url為null則返回null.
} catch (IOException e) {
return null;
}
}
通過這Class.resolveName(String name)中的源代碼和ClassLoader.getResourceAsStream(String name)中的源代碼以及Class.getResourceAsStream(String name)中的原代碼我們易知道上述五種情況是怎么來的。無需記憶。
只需學會數(shù)學推理即可。
大家在看源碼是:發(fā)現(xiàn)Class.resolveName(String name)這個方法是private的,你用普通方法根本調(diào)用不了,下面我順便提一下:如何調(diào)用這個方法。以便大家可以更好的理解這個方法所講的意思。
package com.qls.commonclass;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 用反射調(diào)用ClassLoade中的 private String resolveName(String name)
* 驗證這個方法所講的意思。
* @author 秦林森
*
*/
public class Test7 {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
//得到這個方法。
Method method = Class.class.getDeclaredMethod("resolveName", new Class[]{String.class});
//由于這個方法是private,所以要獲取這個方法的訪問權限
method.setAccessible(true);
//寫一個實例,以便調(diào)用這個方法。
Object obj = Test7.class;//Test這個類所在的包是:com.qls.commonclass
//調(diào)用這個方法
String invoke = (String) method.invoke(obj, new Object[]{"ouyangfeng"});
String invoke2 = (String) method.invoke(obj, new Object[]{"/ouyangfeng"});
System.out.println("invoke="+invoke);
System.out.println("invoke2="+invoke2);
}
}/*
Output:
invoke=com/qls/commonclass/ouyangfeng
invoke2=ouyangfeng
由此可以證明了:以/開頭的字符串"/ouyangfeng"調(diào)用resolveName(String name)
這個方法之后返回的結果是:ouyangfeng
不以/開頭的字符串:"ouyangfeng"返回的結果是:調(diào)用這個方法的包名/name
【在本例中是Test7調(diào)用resolveName(String name),而Test7所在的包是:com.qls.commonclass
所以返回結果是:com/qls/commonclass/ouyangfeng】
*///:~
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
SpringBoot2底層注解@Configuration配置類詳解
這篇文章主要為大家介紹了SpringBoot2底層注解@Configuration配置類詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05
Java避免UTF-8的csv文件打開中文出現(xiàn)亂碼的方法
這篇文章主要介紹了Java避免UTF-8的csv文件打開中文出現(xiàn)亂碼的方法,結合實例形式分析了java操作csv文件時使用utf-16le編碼與utf8編碼相關操作技巧,需要的朋友可以參考下2019-07-07
RestTemplate如何通過HTTP?Basic?Auth認證示例說明
這篇文章主要為大家介紹了RestTemplate如何通過HTTP?Basic?Auth認證的示例說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-03-03
使用Feign調(diào)用時添加驗證信息token到請求頭方式
這篇文章主要介紹了使用Feign調(diào)用時添加驗證信息token到請求頭方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
SpringCloud Gateway動態(tài)路由配置詳解
這篇文章主要為大家介紹了SpringCloud Gateway動態(tài)路由配置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03
使用EasyPoi完成復雜一對多excel表格導出功能全過程
這篇文章主要介紹了使用EasyPoi完成復雜一對多excel表格導出功能全過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12
java實現(xiàn)Composite組合模式的實例代碼
這篇文章主要介紹了java實現(xiàn)Composite組合模式,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01
java HttpURLConnection 發(fā)送文件和字符串信息
這篇文章主要介紹了java HttpURLConnection 發(fā)送文件和字符串信息的相關資料,需要的朋友可以參考下2017-06-06

