archaius(4) 属性对象
讲完上一节,我们就可以使用合理的配置管理器或者实现自己的配置管理来管理我们的配置项了。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) 属性对象的更多相关文章
- HTML DOM 属性 对象
HTML DOM 属性 对象 HTML DOM 节点 在 HTML DOM (Document Object Model) 中, 所有的都是 节点: 文档是文档节点 所有 HTML 元素是元素节点 所 ...
- Spring Boot 环境变量读取 和 属性对象的绑定
网上看到的一些方法,结合我看到的 和我们现在使用的.整理成此文: 第一种方法 参见catoop的博客之 Spring Boot 环境变量读取 和 属性对象的绑定(尊重原创) 第二种方法 class不用 ...
- python 零散记录(七)(下) 新式类 旧式类 多继承 mro 类属性 对象属性
python新式类 旧式类: python2.2之前的类称为旧式类,之后的为新式类.在各自版本中默认声明的类就是各自的新式类或旧式类,但在2.2中声明新式类要手动标明: 这是旧式类为了声明为新式类的方 ...
- JavaScript之面向对象学习二(原型属性对象与in操作符)获取对象中所有属性的方法
1.原型属性对象于in操作符之in单独使用 有两种方式使用in操作符:单独使用和在for-in循环中使用.在单独使用中,代码如下: function Person(){ } Person.protot ...
- 学习pthreads,使用属性对象创建结合线程和分离线程
当我们创建了子线程,是让它犹如脱缰之马,信步驰骋,还是如乖巧听话的孩子,时不时教导一下呢?针对这个问题,本文介绍线程的结合和分离,结构分为三个部分,第一部分给出代码示例,第二部分对代码进行讲解,第三部 ...
- 视图属性+对象动画组件ViewPropertyObjectAnimator
视图属性+对象动画组件ViewPropertyObjectAnimator ViewPropertyObjectAnmator组件是一款对象动画(ObjectAnimator)封装组件.它将视图属 ...
- [十六]SpringBoot 之 读取环境变量和绑定属性对象
1.读取环境变量 凡是被spring管理的类,实现接口EnvironmentAware 重写方法 setEnvironment 可以在工程启动时,获取到系统环境变量和application配置文件中的 ...
- HTML DOM Document对象 元素对象 属性对象 事件对象
DOM Document对象 DOM 元素 对象 DOM 属性 对象 DOM 事件 菜鸟教程上 总结挺全的,就不多废话,链接点进去即可.. 后期对经常用到的会在此更新一些总结..... 开学了...自 ...
- object 属性 对象的继承 (原型, call,apply)
object 为一切对象的基类! 属性:constructor: 对创建对象的函数的引用Prototype: 原型(类型) hasOwnProperty(property):判断对象是否有某个特定的属 ...
随机推荐
- 使用MSF通过MS17-010获取系统权限
---恢复内容开始--- Step1:开启postgresql数据库: /etc/init.d/postgresql start Step2:进入MSF中,搜索cve17-010相关的exp: sea ...
- Jenkins配置总结
1.配置全局 系统管理->全局工具配置 2.配置 自己安装安装jdk,git,以及maven 3.系统管理->系统配置 3.1配置Jenkins URL 3.2 配置SSH Servers ...
- 3d相册展示
示例代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta ...
- 1、Entity Framework Core 3.1入门教程-概述和准备工作
本文章是根据 微软MVP solenovex(杨旭)老师的视频教程编写而来,再加上自己的一些理解. 视频教程地址:https://www.bilibili.com/video/BV1xa4y1v7rR ...
- js byte字节流和数字,字符串之间的转换,包含无符和有符之间的转换
var NumberUtil={ //byte数组转换为int整数 bytesToInt2:function(bytes, off) { var b3 = bytes[off] & 0xFF; ...
- 基于 GitBook 搭建个人博客
目录 基于 GitBook 搭建个人博客 1.为什么要写博客? 2.为什么选择使用 GitBook 来搭建? 3.搭建方式 3.1 GitBook 线上直接搭建 3.2 由基于Node.js的命令工具 ...
- C语言基础练习——打印乘法口诀表
C语言基础练习--打印乘法口诀表 JERRY_Z. ~ 2020 / 8 / 26 转载请注明出处! 代码: /* * @Author: JERRY_Z. * @Date: 2020-08-26 16 ...
- SpringBoot启动注解源码流程学习总结
- javascript正则用法
一.元字符 . 匹配除了换行符以外的字符. \w 匹配字母或者数字或者下划线 \W 匹配不是字母.数字.下划线 \d 匹配数字,相当于[0-9] \D 匹配不是数字的字符 \s ...
- 华为SEO搜索引擎主管招聘内容
http://www.wocaoseo.com/thread-166-1-1.html 华为SEO搜索引擎主管招聘内容: 职位职责 1. 提出全站的SEO策略和实施计划,推动和监督计划实施:负责提升各 ...