Configuration 接口分析
/**
-
配置中心接口,
/
public interface Configuration {
/*- 根据给定的 key 返回对应的值.
- @param key The configuration key.
- @return The associated string.
*/
default String getString(String key) {
return convert(String.class, key, null);
}
/**
- 返回 key 对应的值. 如果找不到,则返回默认值.
- @param key The configuration key.
- @param defaultValue The default value.
- @return The associated string if key is found and has valid
- format, default value otherwise.
*/
default String getString(String key, String defaultValue) {
return convert(String.class, key, defaultValue);
}
/**
- 从配置中心返回对应的值. 这是检索属性值的基本方法. 在 Configuration 接口的典型实现中,
- 其他 get 方法(即返回特定的数据类型) 将在内部使用此方法.
- @param key property to retrieve
- @return the value to which this configuration maps the specified key, or
- null if the configuration contains no mapping for this key.
*/
default Object getProperty(String key) {
return getProperty(key, null);
}
/**
- 从配置中心返回对应的 value 值. 如果配置中心不包含此 key 对应的 value,则返回默认值.
- @param key property to retrieve
- @param defaultValue default value
- @return the value to which this configuration maps the specified key, or default value if the configuration
- contains no mapping for this key.
*/
default Object getProperty(String key, Object defaultValue) {
Object value = getInternalProperty(key);
return value != null ? value : defaultValue;
}
// 待子类实现
Object getInternalProperty(String key);/**
- 检查配置中心是否包含给定的 key.
- @param key the key whose presence in this configuration is to be tested
- @return {@code true} if the configuration contains a value for this
- key, {@code false} otherwise
*/
default boolean containsKey(String key) {
return getProperty(key) != null;
}
// 根据给定的类型,将 key 对应的值转换为对应的类型.
default T convert(Class cls, String key, T defaultValue) {
// we only process String properties for now
String value = (String) getProperty(key);if (value == null) { return defaultValue; } Object obj = value; if (cls.isInstance(value)) { return cls.cast(value); } if (Boolean.class.equals(cls) || Boolean.TYPE.equals(cls)) { obj = Boolean.valueOf(value); } else if (Number.class.isAssignableFrom(cls) || cls.isPrimitive()) { if (Integer.class.equals(cls) || Integer.TYPE.equals(cls)) { obj = Integer.valueOf(value); } else if (Long.class.equals(cls) || Long.TYPE.equals(cls)) { obj = Long.valueOf(value); } else if (Byte.class.equals(cls) || Byte.TYPE.equals(cls)) { obj = Byte.valueOf(value); } else if (Short.class.equals(cls) || Short.TYPE.equals(cls)) { obj = Short.valueOf(value); } else if (Float.class.equals(cls) || Float.TYPE.equals(cls)) { obj = Float.valueOf(value); } else if (Double.class.equals(cls) || Double.TYPE.equals(cls)) { obj = Double.valueOf(value); } } else if (cls.isEnum()) { obj = Enum.valueOf(cls.asSubclass(Enum.class), value); } return cls.cast(obj);
}
}
ConfigurationListener 接口
/**
-
配置侦听器,将在配置侦听更改时得到通知.
*/
public interface ConfigurationListener {/**
- 侦听器回调方法. 一旦侦听器的配置发生任何更改,侦听器就会通过此方法得到通知.
- @param event config change event
*/
void process(ConfigChangeEvent event);
}
DynamicConfiguration 接口
/**
-
动态配置
-
从框架内部的使用场景来看,主要有三种方法:
-
1.getConfig 从配置中心获取管理规则或单个配置项.
-
2.getConfigFile 在启动时从配置中心获取配置文件
-
3.addListener/removeListener 为需要监视的治理规则或配置项添加或删除侦听器.
*/
public interface DynamicConfiguration extends Configuration {
String DEFAULT_GROUP = “dubbo”;/**
- {@link #addListener(String, String, ConfigurationListener)}
- @param key the key to represent a configuration
- @param listener configuration listener
*/
default void addListener(String key, ConfigurationListener listener) {
addListener(key, DEFAULT_GROUP, listener);
}
/**
- {@link #removeListener(String, String, ConfigurationListener)}
- @param key the key to represent a configuration
- @param listener configuration listener
*/
default void removeListener(String key, ConfigurationListener listener) {
removeListener(key, DEFAULT_GROUP, listener);
}
/**
- Register a configuration listener for a specified key
- The listener only works for service governance purpose, so the target group would always be the value user
- specifies at startup or ‘dubbo’ by default. This method will only register listener, which means it will not
- trigger a notification that contains the current value.
- @param key the key to represent a configuration
- @param group the group where the key belongs to
- @param listener configuration listener
*/
void addListener(String key, String group, ConfigurationListener listener);
/**
- Stops one listener from listening to value changes in the specified key.
- @param key the key to represent a configuration
- @param group the group where the key belongs to
- @param listener configuration listener
*/
void removeListener(String key, String group, ConfigurationListener listener);
/**
- Get the governance rule mapped to the given key and the given group
- @param key the key to represent a configuration
- @param group the group where the key belongs to
- @return target configuration mapped to the given key and the given group
*/
default String getRule(String key, String group) {
return getRule(key, group, -1L);
}
/**
- Get the governance rule mapped to the given key and the given group. If the
- rule fails to return after timeout exceeds, IllegalStateException will be thrown.
- @param key the key to represent a configuration
- @param group the group where the key belongs to
- @param timeout timeout value for fetching the target config
- @return target configuration mapped to the given key and the given group, IllegalStateException will be thrown
- if timeout exceeds.
*/
String getRule(String key, String group, long timeout) throws IllegalStateException;
/**
- This method are mostly used to get a compound config file, such as a complete dubbo.properties file.
- Also {@see #getConfig(String, String)}
*/
default String getProperties(String key, String group) throws IllegalStateException {
return getProperties(key, group, -1L);
}
/**
- This method are mostly used to get a compound config file, such as a complete dubbo.properties file.
- Also {@see #getConfig(String, String, long)}
*/
String getProperties(String key, String group, long timeout) throws IllegalStateException;
/**
- Find DynamicConfiguration instance
- @return DynamicConfiguration instance
*/
static DynamicConfiguration getDynamicConfiguration() {
Optional optional = Environment.getInstance().getDynamicConfiguration();
return (DynamicConfiguration) optional.orElseGet(() -> getExtensionLoader(DynamicConfigurationFactory.class)
.getDefaultExtension()
.getDynamicConfiguration(null));
}
/**
- The format is ‘{interfaceName}:[version]:[group]’
- @return
*/
static String getRuleKey(URL url) {
return url.getColonSeparatedKey();
}
}
DynamicConfigurationFactory 接口
定义了获取 DynamicConfiguration 的接口.
ConfigChangeType 枚举
定义了对配置项的操作,比如说新增、修改和删除.
ConfigChangeEvent 定义了对 Config 操作时产生的事件(观察者模式),最重要的就是 configType 这个属性值.
public class ConfigChangeEvent {
private final String key;
private final String value;
private final ConfigChangeType changeType;
public ConfigChangeEvent(String key, String value) {
this(key, value, ConfigChangeType.MODIFIED);
}
public ConfigChangeEvent(String key, String value, ConfigChangeType changeType) {
this.key = key;
this.value = value;
this.changeType = changeType;
}
public String getKey() {
return key;
}
public String getValue() {
return value;
}
public ConfigChangeType getChangeType() {
return changeType;
}
@Override
public String toString() {
return "ConfigChangeEvent{" +
"key='" + key + '\'' +
", value='" + value + '\'' +
", changeType=" + changeType +
'}';
}
}
AbstractDynamicConfigurationFactory 实现了 DynamicConfigurationFactory 的骨架,保证获取 DynamicConfiguration 是线程安全的.
NopDynamicConfiguration 实现的是一个没有任何操作的配置中心,为默认实现.
/**
-
{@link DynamicConfiguration} 的默认扩展名. 如果用户未指定配置中心,或指定的配置扩展名无效,则默认为该配置中心.
*/
public class NopDynamicConfiguration implements DynamicConfiguration {public NopDynamicConfiguration(URL url) {
// no-op
}@Override
public Object getInternalProperty(String key) {
return null;
}@Override
public void addListener(String key, String group, ConfigurationListener listener) {
// no-op
}@Override
public void removeListener(String key, String group, ConfigurationListener listener) {
// no-op
}@Override
public String getRule(String key, String group, long timeout) throws IllegalStateException {
return null;
}@Override
public String getProperties(String key, String group, long timeout) throws IllegalStateException {
return null;
}
}