讲完上一节,我们就可以使用合理的配置管理器或者实现自己的配置管理来管理我们的配置项了。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. 虚拟化技术之kvm虚拟机创建工具virt-install

    在前边的博客中,我们创建KVM虚拟机用到了virt-manager,这个工具是一个图形化工具,创建虚拟机很方便:除此我们还是用virsh define/create +虚拟机配置文件来创建虚拟机,这种 ...

  2. leetcode刷题记录——树

    递归 104.二叉树的最大深度 /** * Definition for a binary tree node. * public class TreeNode { * int val; * Tree ...

  3. python基础 Day1

    Python开发笔记 Day1 1.cpu内存 硬盘 操作系统 cpu:计算机的运算和计算中心,相当于人类大脑 内存:暂时存储数据,临时加载数据应用程序,4G(内存速度快,断电即消失) 硬盘:磁盘,长 ...

  4. 第5章 JDBC/ODBC服务器

    第5章 JDBC/ODBC服务器 Spark SQL也提供JDBC连接支持,这对于让商业智能(BI)工具连接到Spark集群上以 及在多用户间共享一个集群的场景都非常有用.JDBC 服务器作为一个独立 ...

  5. 数字货币比特币以太坊买卖五档行情数据API接口

    数字货币比特币以太坊买卖五档行情数据API接口       数字货币一般包含比特币BTC.以太坊ETH.瑞波币XRP.泰达币USDT.比特币现金BCH.比特币SV.莱特币LTC.柚子币EOS.OKB. ...

  6. Java 8新特性(三):Optional类

    在上一篇介绍Stream流式数据处理的文章中提到了Optional类,这是Java 8新增的一个类,用以解决程序中常见的NullPointerException异常问题.本篇文章将详细介绍Option ...

  7. 系综的实现方式(nve、nvt、npt)

    一.NVE系综 更新位置和速度,v和e恒定. 二.NVT系综 几种实现的方式: 如: fix 1 all nve #更新位置和速度,e和V保持不变.若只有这个命令,就只nve系综,如果和控温命令一起, ...

  8. muduo源码解析6-condtion类

    condition class condition:noncopyable { }; 作用: 实现了最简单condtion操作,包括init,destroy,wait,notify,notifyAll ...

  9. 【C艹】关于sort用法之重构cmp(comp)函数的笔记

    众所周知,balabalabalabala············. 所以掌握sort函数(库文件:<algorithm>)的用法还是很有必要的. 一般选手只会简单地用用sort排一排数组 ...

  10. 使用xShell 连接 docker 使用说明

    方式一:当不知道docker里镜像的root密码的时候 1.从Docker Hub下载需要的镜像 docker pull 镜像名字 2.使用docker run命令启动容器 docker run -i ...