极致之路,没有银弹。不要想着一招毙命,一口吃成个胖子,而是要审时度势,结合当前状况来裁定。
–> 返回专栏总目录 <–
代码下载地址: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