讲完上一节,我们就可以使用合理的配置管理器或者实现自己的配置管理来管理我们的配置项了。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. 【译】New experimental Razor editor for Visual Studio

    随着 Visual Studio 2019 16.7 Preview 4 的发布,现在可以尝试我们新的实验性 Razor 编辑器,用于本地开发,包括 MVC.Razor Page 和 Blazor.我 ...

  2. Gitlab-CI/CD 2

    Gitlab-Runner自动构建服务器搭建2 注册Runner 上一节我们创建了自己的gitlab-runner镜像,并使用docker-compose up -d --build命令运行了一个名为 ...

  3. Jmeter 常用函数(5)- 详解 __property

    如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.html 作用 读取 Jmeter 属性 语法格式 $ ...

  4. JavaScript学习系列博客_30_JavaScript Date 日期对象

    Date - 日期的对象,在JS中通过Date对象来表示一个时间 - 创建一个当前的时间对象 var d = new Date(); - 创建一个指定的时间对象 var d = new Date(&q ...

  5. Shell编程—控制脚本

    1处理信号 1.1信号表 编号 信号名称 缺省操作 解释 1 SIGHUP Terminate 挂起控制终端或进程 2 SIGINT Terminate 来自键盘的中断 3 SIGQUIT Dump ...

  6. 牛客网PAT练兵场-程序运行时间

    题解:无(注意下四舍五入和输出格式即可) 题目地址:https://www.nowcoder.com/questionTerminal/fabbb85fc2d342418bcacdf0148b6130 ...

  7. 牛客网数据库SQL实战解析(1-10题)

    牛客网SQL刷题地址: https://www.nowcoder.com/ta/sql?page=0 牛客网数据库SQL实战解析(01-10题): https://blog.csdn.net/u010 ...

  8. Inno Setup Compiler 中文使用教程

    一.概要 该文章主要解决,Inno Setup Compiler工具的使用问题. 如有什么建议欢迎提出,本人及时修改.[如有任何疑惑可以加Q群:580749909] 二.步骤 (1)下载地址:http ...

  9. PHP - 附件下载

    <?php $file_name = "textuse.zip";//下载文件名 $file_dir = "E:/www/xiazaiwenjian/"; ...

  10. e3mall商城总结12之购物车的实现、以及购物车小计问题、json406报错

    说在前面的话 1.本节主要讲了e3mall购物车的实现方法,我搭建的项目和系统购物车有一些区别,因此这里需要说一下.系统搭建的项目在未登陆的情况下也可以通过cookie进行加入购物车,当用户要下单的时 ...