archaius源码分析之属性对象

  属性对象针对每个属性一对象方式实现操作。

结构如下:

Property  

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

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

基本类型动态属性

  PropertyWrapper及其子类实现了基本类型属性。

  DynamicProperty实现了一个动态属性,内部存储属性名,通过DynamicPropertySupport来获取属性,并实现PropertyListener来监听属性变更。PropertyWrapper内部封装了DynamicProperty实现了具体类型的动态配置,子类指定了特定的类型。

  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;
    }

集合属性

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

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

链式属性

  动态属性链(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;
        }
...
    }

原文地址:https://www.cnblogs.com/zhangwanhua/p/8335027.html

时间: 2024-08-03 14:42:51

archaius源码分析之属性对象的相关文章

archaius源码分析之概述

archaius源码包括以下几个模块: 配置存储文件 就是配置实际存储配置的地方 配置源 获取配置文件数据的地方,通过配置源可以快速获取配置信息.详见:archaius源码分析之配置源 配置管理 实现配置读取,动态更新配置.参见配置:archaius源码分析之配置管理 属性对象 通过配置管理获取配置,实现以配置项来获取配置,具有缓存和指定类型特性. 配置 实现了apache commom 配置接口,对配置源进行管理,动态更新配置. 原文地址:https://www.cnblogs.com/zha

Spring IOC 容器源码分析 - 填充属性到 bean 原始对象

1. 简介 本篇文章,我们来一起了解一下 Spring 是如何将配置文件中的属性值填充到 bean 对象中的.我在前面几篇文章中介绍过 Spring 创建 bean 的流程,即 Spring 先通过反射创建一个原始的 bean 对象,然后再向这个原始的 bean 对象中填充属性.对于填充属性这个过程,简单点来说,JavaBean 的每个属性通常都有 getter/setter 方法,我们可以直接调用 setter 方法将属性值设置进去.当然,这样做还是太简单了,填充属性的过程中还有许多事情要做.

jquery源码分析(四)——回调对象 Callbacks

借用百度百科来说明下回调函数: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应. jQuery回调对象实现恰好利用了设计模式中的观察者模式思想,观察者模式 (pub/sub) 的背后,总的想法是在应用程序中增强松耦合性.并非是在其它对象的方法上的单个对象调用.一个对象作为特定任务或

Qt事件分发机制源码分析之QApplication对象构建过程

我们在新建一个Qt GUI项目时,main函数里会生成类似下面的代码: int main(int argc, char *argv[]) { QApplication application(argc, argv); CQDialog dialog(NULL); dialog.show(); return application.exec(); } 对应的步骤解释如下 1.构建QApplication对象 2.构建CQDialog主界面 3.主界面显示 4.QApplication对象进入事件循

源码分析:Java对象的内存分配

Java对象的分配,根据其过程,将其分为快速分配和慢速分配两种形式,其中快速分配使用无锁的指针碰撞技术在新生代的Eden区上进行分配,而慢速分配根据堆的实现方式.GC的实现方式.代的实现方式不同而具有不同的分配调用层次. 下面就以bytecodeInterpreter解释器对于new指令的解释出发,分析实例对象的内存分配过程: 一.快速分配 1.实例的创建首先需要知道该类型是否被加载和正确解析,根据字节码所指定的CONSTANT_Class_info常量池索引,获取对象的类型信息并调用is_un

lua 源码分析之线程对象lua_State

lua_State 中放的是 lua 虚拟机中的环境表.注册表.运行堆栈.虚拟机的上下文等数据. 从一个主线程(特指 lua 虚拟机中的线程,即 coroutine)中创建出来的新的 lua_State 会共享大部分数据,但会拥有一个独立的运行堆栈.所以一个线程对象拥有一个lua_State. (ps:lua 的coroutine的使用参考: http://blog.csdn.NET/wusheng520/article/details/7954666) lua_State共享的数据部分是全局状

archaius源码分析之配置源

配置源 配置源定义和实现了获取配置文件的方式.有两种配置源,一种是主动拉去方式获取配置,一种是被动监听方式获取配置 类图结构: 接口PolledConfigurationSource定义了获取配置的方法 public PollResult poll(boolean initial, Object checkPoint) throws Exception; initial是否是初次获取,checkPoint上次获取的检查点. JDBCConfigurationSource 从数据库中获取配置信息.

jQuery1.9.1源码分析--数据缓存Data模块

阅读目录 jQuery API中Data的基本使用方法介绍 jQuery.acceptData(elem)源码分析 jQuery.data(elem, name, data)源码分析 internalRemoveData方法源码分析 internalData方法的源码分析 jQuery.fn.extend({data: function( key, value ) {}})源码分析 jQuery.extend({removeData: function( elem, name ) {}})源码分

jQuery.pushStack()原型方法源码分析

这次分析的方法跟前面不同,虽然pushStack也是原型方法之一,但是我们几乎从不用在页面调用,在参考手册里面也没有这个方法的使用说明,但是这个方法还是非常重要的,在使用很多jQuery的其他方式都会隐式的调用此方法: 它为以下方法提供支持:? ? jQuery 对象遍历:.eq()..first()..last()..slice()..map().? ? DOM 查找.过滤:.find()..not()..filter()..closest()..add()..andSelf().? ? DO