package com.ibeifeng.sparkproject.conf;
import java.io.InputStream;
import java.util.Properties;
/**
- 配置管理組件
- 1、配置管理組件可以復(fù)雜,也可以很簡(jiǎn)單恒削,對(duì)于簡(jiǎn)單的配置管理組件來(lái)說(shuō)客们,只要開(kāi)發(fā)一個(gè)類健民,可以在第一次訪問(wèn)它的
時(shí)候锅必,就從對(duì)應(yīng)的properties文件中架专,讀取配置項(xiàng)倒槐,并提供外界獲取某個(gè)配置key對(duì)應(yīng)的value的方法
- 2旬痹、如果是特別復(fù)雜的配置管理組件,那么可能需要使用一些軟件設(shè)計(jì)中的設(shè)計(jì)模式导犹,比如單例模式唱凯、解釋器模式
可能需要管理多個(gè)不同的properties,甚至是xml類型的配置文件
- 3谎痢、我們這里的話磕昼,就是開(kāi)發(fā)一個(gè)簡(jiǎn)單的配置管理組件,就可以了
- @author Administrator
*/
public class ConfigurationManager {
// Properties對(duì)象使用private來(lái)修飾节猿,就代表了其是類私有的
// 那么外界的代碼票从,就不能直接通過(guò)ConfigurationManager.prop這種方式獲取到Properties對(duì)象
// 之所以這么做漫雕,是為了避免外界的代碼不小心錯(cuò)誤的更新了Properties中某個(gè)key對(duì)應(yīng)的value
// 從而導(dǎo)致整個(gè)程序的狀態(tài)錯(cuò)誤,乃至崩潰
private static Properties prop = new Properties();
/**
* 靜態(tài)代碼塊
*
* Java中峰鄙,每一個(gè)類第一次使用的時(shí)候浸间,就會(huì)被Java虛擬機(jī)(JVM)中的類加載器,去從磁盤(pán)上的.class文件中
* 加載出來(lái)吟榴,然后為每個(gè)類都會(huì)構(gòu)建一個(gè)Class對(duì)象魁蒜,就代表了這個(gè)類
*
* 每個(gè)類在第一次加載的時(shí)候,都會(huì)進(jìn)行自身的初始化吩翻,那么類初始化的時(shí)候兜看,會(huì)執(zhí)行哪些操作的呢?
* 就由每個(gè)類內(nèi)部的static {}構(gòu)成的靜態(tài)代碼塊決定狭瞎,我們自己可以在類中開(kāi)發(fā)靜態(tài)代碼塊
* 類第一次使用的時(shí)候细移,就會(huì)加載,加載的時(shí)候熊锭,就會(huì)初始化類弧轧,初始化類的時(shí)候就會(huì)執(zhí)行類的靜態(tài)代碼塊
*
* 因此,對(duì)于我們的配置管理組件碗殷,就在靜態(tài)代碼塊中精绎,編寫(xiě)讀取配置文件的代碼
* 這樣的話,第一次外界代碼調(diào)用這個(gè)ConfigurationManager類的靜態(tài)方法的時(shí)候锌妻,就會(huì)加載配置文件中的數(shù)據(jù)
*
* 而且捺典,放在靜態(tài)代碼塊中,還有一個(gè)好處从祝,就是類的初始化在整個(gè)JVM生命周期內(nèi),有且僅有一次引谜,也就是說(shuō)
* 配置文件只會(huì)加載一次牍陌,然后以后就是重復(fù)使用,效率比較高员咽;不用反復(fù)加載多次
*/
static {
try {
// 通過(guò)一個(gè)“類名.class”的方式毒涧,就可以獲取到這個(gè)類在JVM中對(duì)應(yīng)的Class對(duì)象
// 然后再通過(guò)這個(gè)Class對(duì)象的getClassLoader()方法,就可以獲取到當(dāng)初加載這個(gè)類的JVM
// 中的類加載器(ClassLoader)贝室,然后調(diào)用ClassLoader的getResourceAsStream()這個(gè)方法
// 就可以用類加載器契讲,去加載類加載路徑中的指定的文件
// 最終可以獲取到一個(gè),針對(duì)指定文件的輸入流(InputStream)
InputStream in = ConfigurationManager.class
.getClassLoader().getResourceAsStream("my.properties");
// 調(diào)用Properties的load()方法滑频,給它傳入一個(gè)文件的InputStream輸入流
// 即可將文件中的符合“key=value”格式的配置項(xiàng)捡偏,都加載到Properties對(duì)象中
// 加載過(guò)后,此時(shí)峡迷,Properties對(duì)象中就有了配置文件中所有的key-value對(duì)了
// 然后外界其實(shí)就可以通過(guò)Properties對(duì)象獲取指定key對(duì)應(yīng)的value
prop.load(in);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 獲取指定key對(duì)應(yīng)的value
*
* 第一次外界代碼银伟,調(diào)用ConfigurationManager類的getProperty靜態(tài)方法時(shí)你虹,JVM內(nèi)部會(huì)發(fā)現(xiàn)
* ConfigurationManager類還不在JVM的內(nèi)存中
*
* 此時(shí)JVM,就會(huì)使用自己的ClassLoader(類加載器)彤避,去對(duì)應(yīng)的類所在的磁盤(pán)文件(.class文件)中
* 去加載ConfigurationManager類傅物,到JVM內(nèi)存中來(lái),并根據(jù)類內(nèi)部的信息琉预,去創(chuàng)建一個(gè)Class對(duì)象
* Class對(duì)象中董饰,就包含了類的元信息,包括類有哪些field(Properties prop)圆米;有哪些方法(getProperty)
*
* 加載ConfigurationManager類的時(shí)候卒暂,還會(huì)初始化這個(gè)類,那么此時(shí)就執(zhí)行類的static靜態(tài)代碼塊
* 此時(shí)咱們自己編寫(xiě)的靜態(tài)代碼塊中的代碼榨咐,就會(huì)加載my.properites文件的內(nèi)容介却,到Properties對(duì)象中來(lái)
*
* 下一次外界代碼,再調(diào)用ConfigurationManager的getProperty()方法時(shí)块茁,就不會(huì)再次加載類齿坷,不會(huì)再次初始化
* 類,和執(zhí)行靜態(tài)代碼塊了数焊,所以也印證了永淌,我們上面所說(shuō)的,類只會(huì)加載一次佩耳,配置文件也僅僅會(huì)加載一次
*
* @param key
* @return value
*/
public static String getProperty(String key) {
return prop.getProperty(key);
}
/**
* 獲取整數(shù)類型的配置項(xiàng)
* @param key
* @return value
*/
public static Integer getInteger(String key) {
String value = getProperty(key);
try {
return Integer.valueOf(value);
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
/**
* 獲取布爾類型的配置項(xiàng)
* @param key
* @return value
*/
public static Boolean getBoolean(String key) {
String value = getProperty(key);
try {
return Boolean.valueOf(value);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 獲取Long類型的配置項(xiàng)
* @param key
* @return
*/
public static Long getLong(String key) {
String value = getProperty(key);
try {
return Long.valueOf(value);
} catch (Exception e) {
e.printStackTrace();
}
return 0L;
}
}