archaius源码分析之属性对象
Posted zwh1988
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了archaius源码分析之属性对象相关的知识,希望对你有一定的参考价值。
讲完上一节,我们就可以使用合理的配置管理器或者实现自己的配置管理来管理我们的配置项了。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源码分析之属性对象的主要内容,如果未能解决你的问题,请参考以下文章
(18)Blender源码分析之闪屏窗口的菜单python代码属性识别