極致之路,沒有銀彈。不要想着一招斃命,一口吃成個胖子,而是要審時度勢,結合當前狀況來裁定。
–> 返回專欄總目錄 <–
代碼下載地址:https://github.com/f641385712/netflix-learning
前言
上篇文章完整的介紹了Commons Configuration
的Builder機制,並且輔以示例介紹瞭如何使用。
Commons Configuration2.x
推薦我們使用Builder去構建一個Configuration
實例,但奈何實際使用起來着實比較麻煩,怎麼破?
本文將介紹兩個“工具類”:Parameters
和Configurations
,分別能夠簡化你對參數的構建和對Builder構建器創建過程,當然還包含一步到位的直接構建出Configuration
實例的方法。
說明:說這兩個API是工具類有點牽強,畢竟方法都不是static靜態方法~
正文
構建一個BuilderParameters
或者一個Configuration
的步驟是較爲繁瑣的,這兩個API就是爲簡化這些步驟而生。
說明:Xxx
s
結尾經常用於表示幫助類、工具類,形如Collections、Arrays等等…
Parameters
一個工具類,用於創建用於初始化的參數對象配置生成器對象。
與它相關的還有兩個API需要先行介紹:DefaultParametersHandler
和DefaultParametersManager
。
DefaultParametersHandler
用於設置特定的默認值的接口。
public interface DefaultParametersHandler<T> {
void initializeDefaults(T parameters);
}
這個接口很簡單:爲指定參數T設置默認值。它有唯一實現類CopyObjectDefaultHandler
用於給BuilderParameters
設置默認值。
說明:
CopyObjectDefaultHandler
雖然是內置的唯一實現類,但是並沒有被系統用到過,使用者可按需自取
public class CopyObjectDefaultHandler implements DefaultParametersHandler<Object> {
private final BuilderParameters source;
... // 省略構造器和get方法
@Override
public void initializeDefaults(final Object parameters) {
try {
BeanHelper.copyProperties(parameters, getSource().getParameters());
BeanHelper.copyProperties(parameters, getSource());
} catch (final Exception e) {
throw new ConfigurationRuntimeException(e);
}
}
}
CopyObjectDefaultHandler
處理方式:僅僅只是把你傳進來的BuilderParameters
作爲source,通過反射覆制到目標Object身上而已(注意:目標是Object,而非必須BuilderParameters
),個人覺得基本沒啥卵用。
DefaultParametersManager
它是用於管理DefaultParametersHandler
們的管理器,因爲對於一個Class類型上可以有多個DefaultParametersHandler
作用於它的,所以又抽象出DefaultHandlerData
來加以管理,並且還加入了處理繼承、接口實現的匹配的能力(大多情況亦無需關心)。
public class DefaultParametersManager {
// 管理着DefaultParametersHandler的集合
private final Collection<DefaultHandlerData> defaultHandlers;
// 線程安全
public DefaultParametersManager() {
defaultHandlers = new CopyOnWriteArrayList<>();
}
...
// 向管理器註冊一個DefaultParametersHandler
public <T> void registerDefaultsHandler(final Class<T> paramsClass, final DefaultParametersHandler<? super T> handler, final Class<?> startClass) {
...
defaultHandlers.add(new DefaultHandlerData(handler, paramsClass, startClass));
}
... // 省略unregisterDefaultsHandler方法
// 這是它最重要的一個方法:給BuilderParameters設置初始化值
// 這時候註冊在它上面的所有的`DefaultParametersHandler#initializeDefaults`都會執行
// 該方法在代理對象創建完成後,立馬會執行initializeParameters方法完成初始化
public void initializeParameters(final BuilderParameters params) {
if (params != null) {
for (final DefaultHandlerData dhd : defaultHandlers) {
dhd.applyHandlerIfMatching(params);
}
}
}
}
對於每個Class類型是可以有多個DefaultParametersHandler
爲它設置默認值的,initializeParameters()
方法會在每次代理對象創建後,完成初始化賦值操作,也算是給調用者留的一個鉤子。
介紹完兩個前置API,下面正式看看Parameters
提供的API們,我截圖如下:
部分源碼解讀:
Parameters:
// 爲指定類型配置一個DefaultParametersHandler,用於自動設置初始值
public <T> void registerDefaultsHandler(final Class<T> paramsClass, final DefaultParametersHandler<? super T> handler) {
getDefaultParametersManager().registerDefaultsHandler(paramsClass, handler);
}
// 因BasicXXX不是抽象類,所以直接new即可得到實例
public BasicBuilderParameters basic() {
return new BasicBuilderParameters();
}
// 請注意:返回的是這個接口的JDK動態代理對象~~~
public FileBasedBuilderParameters fileBased() {
return createParametersProxy(new FileBasedBuilderParametersImpl(), FileBasedBuilderParameters.class);
}
public CombinedBuilderParameters combined() { ... }
...
public XMLBuilderParameters xml()
public PropertiesBuilderParameters properties()
...
精妙之處在於:XMLBuilderParameters/XMLBuilderParameters
這些均是接口,這裏通過Parameters
生成代理,使得這些接口便可直接使用了,非常方面。這種通用設計(代理對象的生成)是非常值得點讚的~
FileBasedBuilderParameters
和FileBasedBuilderParametersImpl
的區別:
- 後者並不是前者(接口的實現類),即使命名上看其起來非常像
- 兩者均實現了接口
FileBasedBuilderProperties
和BasicBuilderProperties
,可以設置FileBased
屬性和基本屬性 - 兩者均是
BuilderParameters
的實現
總的來說,兩者功能相似,FileBasedBuilderParameters
需要結合Parameters
一起使用,而後者使用者可單獨使用。
使用示例
非常經典的使用案例:
@Test
public void fun4() throws ConfigurationException {
FileBasedConfigurationBuilder<PropertiesConfiguration> builder = new FileBasedConfigurationBuilder<>(PropertiesConfiguration.class);
Parameters params = new Parameters();
// 配置一個FileBased參數即可
FileBasedBuilderParameters builderParameters = params.fileBased().setThrowExceptionOnMissing(true)
.setEncoding("UTF-8")
.setListDelimiterHandler(new DefaultListDelimiterHandler(','))
.setFileName("1.properties");
builder.configure(builderParameters);
System.out.println(builderParameters.getClass());
ConfigurationUtils.dump(builder.getConfiguration(),System.out);
}
控制檯打印:
class com.sun.proxy.$Proxy4 // 可以看到 builderParameters是個JDK代理對象哦
common.name=YourBatman
common.age=18
common.addr=China
common.count=4
common.fullname=${common.name}-Bryant
java.version=1.8.123
至少可以看到,在參數構建BuilderParameters
方面,比之前優雅了很多。
Configurations
如果Parameters
你感覺離得稍遠,那麼Configurations
這個類你不應該陌生。
它也是,一個工具類,它簡化了標準配置的創建和他們的Builder們。也就是說它能方便的創建builder實例,也能一步到位的方便創建出Configuration
實例。
部分源碼解讀:
public class Configurations {
// BuilderParameters等等統一交給它來構建嘍
private final Parameters parameters;
... // 省略構造器
// 快速構建出一個FileBasedConfigurationBuilder實例
// 它可以構建出形如PropertiesConfiguration
public <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> fileBasedBuilder(final Class<T> configClass, final File file) {
return createFileBasedBuilder(configClass, fileParams(file));
}
... // 省略重載方法
// 注意和上面的區別哦:此處一步到位,返回的就是一個Configuration實例
public <T extends FileBasedConfiguration> T fileBased(final Class<T> configClass, final String path) throws ConfigurationException {
return fileBasedBuilder(configClass, path).getConfiguration();
}
... // 同理還有如下搭配
// propertiesBuilder()/properties()
// xmlBuilder()/xml()
// iniBuilder()/ini()
// combinedBuilder()/combined()
}
源碼解讀夠直接、夠簡單,因爲這個工具類沒太好好說的,看個使用示例一學便會。
使用示例
@Test
public void fun5() throws ConfigurationException {
// 當然,絕大多數情況下,空構造new Configurations()即可
// Parameters params = new Parameters();
// Configurations configs = new Configurations(params);
Configurations configs = new Configurations();
PropertiesConfiguration configuration = configs.properties("1.properties");
ConfigurationUtils.dump(configuration,System.out);
}
運行程序,控制檯打印同上。
總結
關於Commons Configuration2.x快速構建工具類Parameters和Configurations就介紹到這了,看完之後有木有一種爽感,編碼過程再一次得到了解放有木有~
聲明
原創不易,碼字不易,多謝你的點贊、收藏、關注。把本文分享到你的朋友圈是被允許的,但拒絕抄襲
。你也可【左邊掃碼/或加wx:fsx641385712】邀請你加入我的 Java高工、架構師 系列羣大家庭學習和交流。
- [享學Netflix] 一、Apache Commons Configuration:你身邊的配置管理專家
- [享學Netflix] 二、Apache Commons Configuration事件監聽機制及使用ReloadingStrategy實現熱更新
- [享學Netflix] 三、Apache Commons Configuration2.x全新的事件-監聽機制
- [享學Netflix] 四、Apache Commons Configuration2.x文件定位系統FileLocator和FileHandler
- [享學Netflix] 五、Apache Commons Configuration2.x別樣的Builder模式:ConfigurationBuilder