讲完上一节,我们就可以使用合理的配置管理器或者实现自己的配置管理来管理我们的配置项了。archaius还提供了一种新的配置使用的方式。

动态属性对象

  动态属性对象针对每个配置项以对象方式进行操作,并且保证配置动态更新,archaius提供了以下属性对象:DynamicFloatProperty、DynamicDoubleProperty、DynamicLongProperty、DynamicIntProperty、DynamicBooleanProperty、DynamicStringProperty。实现原理如下:

public class DynamicFloatProperty extends PropertyWrapper<Float> {
public DynamicFloatProperty(String propName, float defaultValue) {
super(propName, Float.valueOf(defaultValue));
}
public float get() {
return prop.getFloat(defaultValue).floatValue();
}
@Override
public Float getValue() {
return get();
}
}

  动态属性对象都继承PropertyWrapper,PropertyWrapper仅仅是封装了一个DynamicProperty来实现。DynamicProperty实现了一个动态属性,内部存储属性名,通过DynamicPropertySupport来获取属性,并实现PropertyListener来监听属性变更。(DynamicPropertySupport是一个静态变量,也就是说所有的动态属性都使用一个DynamicPropertySupport)。

private volatile static DynamicPropertySupport dynamicPropertySupportImpl;
static synchronized void initialize(DynamicPropertySupport config) {
dynamicPropertySupportImpl = config;
config.addConfigurationListener(new DynamicPropertyListener());
updateAllProperties();
}
static void registerWithDynamicPropertySupport(DynamicPropertySupport config) {
initialize(config);
}

  DynamicPropertySupport自定义了获取和监听配置项的方法。

public interface DynamicPropertySupport {
String getString(String propName);
void addConfigurationListener(PropertyListener expandedPropertyListener);
}

  PropertyListener定义了监听接口

public interface PropertyListener {
/**当配置源被加载时调用
*/
public void configSourceLoaded(Object source);
/**当新增某一个配置项
*/
public void addProperty(Object source, String name, Object value, boolean beforeUpdate);
/**当改变某一个配置项
*/
public void setProperty(Object source, String name, Object value, boolean beforeUpdate);
/**当删除某一个配置项
*/
public void clearProperty(Object source, String name, Object value, boolean beforeUpdate);
/**当清除所有配置项时
*/
public void clear(Object source, boolean beforeUpdate);
}

  DynamicPropertySupport子类ConfigurationBackedDynamicPropertySupportImpl封装了一个apach common的AbstractConfiguration,本质是也就是通过apach common的AbstractConfiguration实现。

    @Override
public String getString(String key) {
...
if (values.length == 0) {
return config.getString(key);
}
...
}
@Override
public void addConfigurationListener(PropertyListener expandedConfigListener) {
ExpandedConfigurationListenerAdapter nl = new ExpandedConfigurationListenerAdapter(expandedConfigListener);
config.addConfigurationListener(nl);
}

缓存属性对象

  archaius还提供了缓存属性对象(CachedDynamicBooleanProperty、CachedDynamicDoubleProperty、CachedDynamicFloatProperty、CachedDynamicIntProperty、CachedDynamicLongProperty),本质就是在初始化时获取配置并在内存中暂存这个配置数据,并且监听配置变动,如果有变动,更新内存配置。

public class CachedDynamicBooleanProperty extends DynamicBooleanProperty {
protected volatile boolean primitiveValue;
public CachedDynamicBooleanProperty(String propName, boolean defaultValue) {
super(propName, defaultValue);
this.primitiveValue = chooseValue();
}
@Override
protected void propertyChanged() {
this.primitiveValue = chooseValue();
}
protected boolean chooseValue() {
return prop.getBoolean(defaultValue).booleanValue();
}
@Override
public boolean get() {
return primitiveValue;
}
@Override
public Boolean getValue() {
return get();
}
}

属性对象工厂

  DynamicPropertyFactory是创建动态属性的工厂类。有两种方式初始化,initWithConfigurationSource通过指定AbstractConfiguration来初始化,getInstance通过默认的AbstractConfiguration来初始化。AbstractConfiguration会被封装成DynamicPropertySupport被DynamicProperty使用。

public static DynamicPropertyFactory initWithConfigurationSource(AbstractConfiguration config) {
synchronized (ConfigurationManager.class) {
...
if (config instanceof DynamicPropertySupport) {
return initWithConfigurationSource((DynamicPropertySupport) config);
}
return initWithConfigurationSource(new ConfigurationBackedDynamicPropertySupportImpl(config));
}
} public static DynamicPropertyFactory initWithConfigurationSource(DynamicPropertySupport dynamicPropertySupport) {
synchronized (ConfigurationManager.class) {
...
DynamicProperty.registerWithDynamicPropertySupport(support);
initializedWithDefaultConfig = false;
return instance;
}
}
 public static DynamicPropertyFactory getInstance() {
if (config == null) {
synchronized (ConfigurationManager.class) {
if (config == null) {
AbstractConfiguration configFromManager = ConfigurationManager.getConfigInstance();
if (configFromManager != null) {
initWithConfigurationSource(configFromManager);
initializedWithDefaultConfig = !ConfigurationManager.isConfigurationInstalled();
logger.info("DynamicPropertyFactory is initialized with configuration sources: " + configFromManager);
}
}
}
}
return instance;
}

类图:

Property  

  定义了属性对象的基本方法,主要为获取属性值,获取默认值,获取属性命令,管理回调函数。

public interface Property<T> {
T getValue();
T getDefaultValue();
String getName();
long getChangedTimestamp();
void addCallback(Runnable callback);
void removeAllCallbacks();
}

 

集合属性

  DynamicListProperty,DynamicSetProperty实现了集合属性,底层通过DynamicStringProperty实现,属性值通过分隔符分割。

protected void load() {
if (delegate.get() == null) {
values = defaultValues;
} else {
values = transform(split(delegate.get()));
}
}

  DynamicMapProperty是DynamicListProperty子类,将DynamicListProperty的每一项再通过=进行分隔组成map集合。

链式属性

  动态属性链(ChainLink),内部包含一个动态类属性和指向下一个动态类属性。如果当前动态类属性无法获得值,则会获取下一个动态类属性返回。每一个属性的值是一个链式的结构,每个节点都会存储一个属性值,获取属性值时,会一个节点一个节点获取,直到取到符合要求的值。ChainLink代表链式中的一个节点,内部有pReference代表最终的属性值节点,next指向下一个节点。getReferencedProperty是该节点存储的属性值。checkAndFlip方法逻辑,当当前节点是最后一个节点时,当前节点就是最终属性值节点;当当前节点不是最后一个节点时,如果当前节点是可用属性值,则当前节点为属性值节点,如果当前节点是不可用值,则设置下一个节点为最终的属性值节点。get方法逻辑,如果当前节点为最终属性值节点,获取当前节点值,如果当前节点不是属性节点,通过下一个节点获取值。

public static abstract class ChainLink<T> implements Property<T> {
...
private final AtomicReference<ChainLink<T>> pReference;
private final ChainLink<T> next;
public abstract boolean isValueAcceptable();
protected abstract Property<T> getReferencedProperty();
public ChainLink(T defaultValue) {
next = null;
pReference = new AtomicReference<ChainLink<T>>(this);
...
}
public ChainLink(ChainLink<T> nextProperty) {
next = nextProperty;
pReference = new AtomicReference<ChainLink<T>>(next);
...
}
protected void checkAndFlip() {
if(next == null) {
pReference.set(this);
return;
}
if (this.isValueAcceptable()) {
pReference.set(this);
} else {
pReference.set(next);
}
for (Runnable r : callbacks) {
r.run();
}
}
public T get() {
if (pReference.get() == this) {
return this.getValue();
} else {
return pReference.get().get();
}
}
@Override
public T getValue() {
return getReferencedProperty().getValue();
}
...
}

  子类BooleanProperty为例,DynamicBooleanPropertyThatSupportsNull是实际获取属性值的类,

public static class BooleanProperty extends ChainLink<Boolean> {

        private final DynamicBooleanPropertyThatSupportsNull sProp;
...
public BooleanProperty(String name, BooleanProperty next) {
super(next); // setup next pointer
sProp = new DynamicBooleanPropertyThatSupportsNull(name, null);
...
checkAndFlip();
}
@Override
public boolean isValueAcceptable() {
return (sProp.getValue() != null);
}
@Override
protected Property<Boolean> getReferencedProperty() {
return sProp;
}
...
}

类图

archaius(4) 属性对象的更多相关文章

  1. HTML DOM 属性 对象

    HTML DOM 属性 对象 HTML DOM 节点 在 HTML DOM (Document Object Model) 中, 所有的都是 节点: 文档是文档节点 所有 HTML 元素是元素节点 所 ...

  2. Spring Boot 环境变量读取 和 属性对象的绑定

    网上看到的一些方法,结合我看到的 和我们现在使用的.整理成此文: 第一种方法 参见catoop的博客之 Spring Boot 环境变量读取 和 属性对象的绑定(尊重原创) 第二种方法 class不用 ...

  3. python 零散记录(七)(下) 新式类 旧式类 多继承 mro 类属性 对象属性

    python新式类 旧式类: python2.2之前的类称为旧式类,之后的为新式类.在各自版本中默认声明的类就是各自的新式类或旧式类,但在2.2中声明新式类要手动标明: 这是旧式类为了声明为新式类的方 ...

  4. JavaScript之面向对象学习二(原型属性对象与in操作符)获取对象中所有属性的方法

    1.原型属性对象于in操作符之in单独使用 有两种方式使用in操作符:单独使用和在for-in循环中使用.在单独使用中,代码如下: function Person(){ } Person.protot ...

  5. 学习pthreads,使用属性对象创建结合线程和分离线程

    当我们创建了子线程,是让它犹如脱缰之马,信步驰骋,还是如乖巧听话的孩子,时不时教导一下呢?针对这个问题,本文介绍线程的结合和分离,结构分为三个部分,第一部分给出代码示例,第二部分对代码进行讲解,第三部 ...

  6. 视图属性+对象动画组件ViewPropertyObjectAnimator

    视图属性+对象动画组件ViewPropertyObjectAnimator   ViewPropertyObjectAnmator组件是一款对象动画(ObjectAnimator)封装组件.它将视图属 ...

  7. [十六]SpringBoot 之 读取环境变量和绑定属性对象

    1.读取环境变量 凡是被spring管理的类,实现接口EnvironmentAware 重写方法 setEnvironment 可以在工程启动时,获取到系统环境变量和application配置文件中的 ...

  8. HTML DOM Document对象 元素对象 属性对象 事件对象

    DOM Document对象 DOM 元素 对象 DOM 属性 对象 DOM 事件 菜鸟教程上 总结挺全的,就不多废话,链接点进去即可.. 后期对经常用到的会在此更新一些总结..... 开学了...自 ...

  9. object 属性 对象的继承 (原型, call,apply)

    object 为一切对象的基类! 属性:constructor: 对创建对象的函数的引用Prototype: 原型(类型) hasOwnProperty(property):判断对象是否有某个特定的属 ...

随机推荐

  1. extJS--尚

    ExtJS依赖JavaScript,JavaScript推荐两本书:<JavaScript高级程序设计>初阶阶段, <JavaScript设计模式>中级阶段 fun1();// ...

  2. TS流解码过程-ES-PES-PTS-DTS

    转载自http://blog.chinaunix.net/uid-9688646-id-1998407.html TS 流解码过程: 1. 获取TS中的PAT 2. 获取TS中的PMT 3. 根据PM ...

  3. SwitchyOmega 配置

    1.google 扩展程序里面的chrome 网上应用店里面安装Proxy SwitchyOmega 2.新建情景模式 3.配置代理 4.自动切换添加新建的情景模式,最后保存

  4. 操作系统-I/O(5)I/O软件的层次结构

    IO软件的设计目标: (1)高效率:改善设备效率,尤其是磁盘I/O操作的效率 (2)通用性:用统一的标准来管理所有设备 IO软件的设计思路: 把软件组织成层次结构,低层软件用来屏蔽硬件细节,高层软件向 ...

  5. latex:矩阵环境

    矩阵的最大列数值是在MaxMatrixCols计数器中设定的,默认值是10.可使用计数器设置命令修改其值,例如需要用到15列:\setcounter{MaxMatrixCols}{15};当超宽矩阵排 ...

  6. centos6.8上安装部署 jhipster-registry

    必备环境:jdk8,git,maven 1.安装nodejs #由于采用编译的方式很容易出现一些意外的惊喜,所以我们这儿直接用yum命令安装 #1.查看nodejs版本(命令中不要加 -y 如果版本不 ...

  7. 符合SEO的网站标题应该怎么写

    http://www.wocaoseo.com/thread-96-1-1.html 的seo网站标题既能提起读者的点击欲望,又能搜索引擎中获得好的排名,这两着之间有着有有一些联系,网站的标题若要从s ...

  8. 淘宝ios端弹窗-2020年3月25日

  9. PAT-B1009 说反话 - 字符串反转

    1009 说反话 (20分) 给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出. 输入格式: 测试输入包含一个测试用例,在一行内给出总长度不超过 80 的字符串.字符串由若干单词和若干空格组 ...

  10. 数字电路基础(二)TTL与非门输入端悬空和接大电阻的问题

    引言 我们在做那些判断与非门输入输出的时候,常常把输入端悬空和接大电阻作为高电平输入处理,比如下边这一例题: 很显然,我们无法直接从与非门逻辑图中看出其内部工作原理,那我们该如何分析呢?那肯定是去分析 ...