package com.ctrip.framework.apollo.enums;
// 变更类型
public enum PropertyChangeType {
ADDED, // 新增
MODIFIED, // 更新
DELETED; // 删除
private PropertyChangeType() {
}
}
package com.ctrip.framework.apollo.model;
import com.ctrip.framework.apollo.enums.PropertyChangeType;
// 事件中绑定的数据,此为:变更数据
public class ConfigChange {
// 关键key
private final String namespace;
// 属性名称
private final String propertyName;
// 旧值
private String oldValue;
// 新值
private String newValue;
// 变更类型
private PropertyChangeType changeType;
public ConfigChange(String namespace,
String propertyName,
String oldValue,
String newValue,
PropertyChangeType changeType) {
this.namespace = namespace;
this.propertyName = propertyName;
this.oldValue = oldValue;
this.newValue = newValue;
this.changeType = changeType;
}
public String getPropertyName() {
return this.propertyName;
}
public String getOldValue() {
return this.oldValue;
}
public String getNewValue() {
return this.newValue;
}
public PropertyChangeType getChangeType() {
return this.changeType;
}
public void setOldValue(String oldValue) {
this.oldValue = oldValue;
}
public void setNewValue(String newValue) {
this.newValue = newValue;
}
public void setChangeType(PropertyChangeType changeType) {
this.changeType = changeType;
}
public String getNamespace() {
return this.namespace;
}
// 格式化输出
public String toString() {
StringBuilder sb = new StringBuilder("ConfigChange{");
sb.append("namespace='").append(this.namespace).append('\'');
sb.append(", propertyName='").append(this.propertyName).append('\'');
sb.append(", oldValue='").append(this.oldValue).append('\'');
sb.append(", newValue='").append(this.newValue).append('\'');
sb.append(", changeType=").append(this.changeType);
sb.append('}');
return sb.toString();
}
}
package com.ctrip.framework.apollo.model;
import java.util.Map;
import java.util.Set;
// 配置数据变更事件
public class ConfigChangeEvent {
// 当前事件,属于哪一个namespace
private final String m_namespace;
// 当前事件,有哪些变更数据(是一个map)
private final Map<String, ConfigChange> m_changes;
// 构造器注入
public ConfigChangeEvent(/**具体的namespace**/String namespace,
/**涉及到的变更内容**/Map<String, ConfigChange> changes) {
this.m_namespace = namespace;
this.m_changes = changes;
}
// 拿到当前事件的变更Keys
public Set<String> changedKeys() {
return this.m_changes.keySet();
}
// 根据变更key拿到具体的变更内容
public ConfigChange getChange(String key) {
return (ConfigChange)this.m_changes.get(key);
}
// 检测具体的key是否发生变化(有变化的话,当前事件绑定的变更数据中会有该key的数据,没有则说明,该key无变化)
public boolean isChanged(String key) {
return this.m_changes.containsKey(key);
}
// 拿到当前事件对应的namespace
public String getNamespace() {
return this.m_namespace;
}
}
package com.ctrip.framework.apollo.spring.property;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import org.springframework.core.MethodParameter;
// 属性值对象
public class SpringValue {
// 方法参数
private MethodParameter methodParameter;
// 属性
private Field field;
// 弱引用
private WeakReference<Object> beanRef;
// bean名称
private String beanName;
// key
private String key;
// 占位符
private String placeholder;
// 目标类型
private Class<?> targetType;
// 通用类型
private Type genericType;
// Json否
private boolean isJson;
// 构造器注入·1
public SpringValue(String key, String placeholder, Object bean, String beanName, Field field, boolean isJson) {
this.beanRef = new WeakReference(bean);
this.beanName = beanName;
this.field = field;
this.key = key;
this.placeholder = placeholder;
this.targetType = field.getType();
this.isJson = isJson;
if (isJson) {
this.genericType = field.getGenericType();
}
}
// 构造器注入·2
public SpringValue(String key, String placeholder, Object bean, String beanName, Method method, boolean isJson) {
this.beanRef = new WeakReference(bean);
this.beanName = beanName;
this.methodParameter = new MethodParameter(method, 0);
this.key = key;
this.placeholder = placeholder;
Class<?>[] paramTps = method.getParameterTypes();
this.targetType = paramTps[0];
this.isJson = isJson;
if (isJson) {
this.genericType = method.getGenericParameterTypes()[0];
}
}
// 更新当前属性值
public void update(Object newVal) throws IllegalAccessException, InvocationTargetException {
if (this.isField()) {
this.injectField(newVal);
} else {
this.injectMethod(newVal);
}
}
private void injectField(Object newVal) throws IllegalAccessException {
Object bean = this.beanRef.get();
if (bean != null) {
boolean accessible = this.field.isAccessible();
this.field.setAccessible(true);
this.field.set(bean, newVal);
this.field.setAccessible(accessible);
}
}
private void injectMethod(Object newVal) throws InvocationTargetException, IllegalAccessException {
Object bean = this.beanRef.get();
if (bean != null) {
this.methodParameter.getMethod().invoke(bean, newVal);
}
}
public String getBeanName() {
return this.beanName;
}
public Class<?> getTargetType() {
return this.targetType;
}
public String getPlaceholder() {
return this.placeholder;
}
public MethodParameter getMethodParameter() {
return this.methodParameter;
}
// 是否是属性
public boolean isField() {
return this.field != null;
}
public Field getField() {
return this.field;
}
public Type getGenericType() {
return this.genericType;
}
public boolean isJson() {
return this.isJson;
}
// 是否失效判定:当前对象是否存在弱引用
boolean isTargetBeanValid() {
return this.beanRef.get() != null;
}
public String toString() {
Object bean = this.beanRef.get();
if (bean == null) {
return "";
} else {
return this.isField() ? String.format("key: %s, beanName: %s, field: %s.%s", this.key, this.beanName, bean.getClass().getName(), this.field.getName()) : String.format("key: %s, beanName: %s, method: %s.%s", this.key, this.beanName, bean.getClass().getName(), this.methodParameter.getMethod().getName());
}
}
}
package com.ctrip.framework.apollo.spring.property;
import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.springframework.beans.factory.BeanFactory;
// apollo定制的@Value注册器
public class SpringValueRegistry {
// 清理时间频率
private static final long CLEAN_INTERVAL_IN_SECONDS = 5L;
// 注册目标对象集合:按照注册Bean工厂对象作一级区分,然后按照Key做二级区分,且目标数据为多个
private final Map<BeanFactory, Multimap<String, SpringValue>> registry = Maps.newConcurrentMap
// 原子:是否完成初始化标记,默认false
private final AtomicBoolean initialized = new AtomicBoolean(false);
// 锁
private final Object LOCK = new Object();
public SpringValueRegistry() {
}
// 注册方法
public void register(BeanFactory beanFactory, // bean工厂对象
String key, // 属性Key
SpringValue springValue // 属性值对象
) {
// 如果当前已经完成注册的目标集合中含有当前Bean工厂对象
if (!this.registry.containsKey(beanFactory)) {
// 上锁
synchronized(this.LOCK) {
// 如果当前注册器目标数据列表中,没有找到该Bean工厂对象
if (!this.registry.containsKey(beanFactory)) {
// 则完成注册(为bean工厂对象创建一个空Multimap,空容器)
this.registry.put(beanFactory,
Multimaps.synchronizedListMultimap(
LinkedListMultimap.create()
)
);
}
}
}
// 开始往注册的目标集合灌数据:数据结构如:<beanFactory,<key:springValue>>
((Multimap)this.registry.get(beanFactory)).put(key, springValue);
// 标记,该apollo定制的@Value注册器,完成了初始化
// 重置标记=true
if (this.initialized.compareAndSet(false, true)) {
// 开始初始化操作
this.initialize();
}
}
// 根据Bean工厂对象和Key获取目标属性值集合,一个key:多个value,多条数据,返回这多条value的汇总的集合对象
public Collection<SpringValue> get(BeanFactory beanFactory, String key) {
Multimap<String, SpringValue> beanFactorySpringValues = (Multimap)this.registry.get(beanFactory);
return beanFactorySpringValues == null
? null
: beanFactorySpringValues.get(key) // Multimap的get操作
;
}
// 私有方法:初始化逻辑
private void initialize() {
//
Executors.newSingleThreadScheduledExecutor(
// apollo定制了一个ThreadFactory(实现ThreadFactory接口的实现类)
// 定制了一些关于线程的操作,命名规则,创建和关闭操作等
ApolloThreadFactory.create("SpringValueRegistry", true)
).scheduleAtFixedRate(
// 具体的任务,开辟独立线程执行(从上面定制的ApolloThreadFactory中创建)
new Runnable() {
public void run() {
try {
// 扫描清理动作
SpringValueRegistry.this.scanAndClean();
} catch (Throwable var2) {
var2.printStackTrace();
}
}
},
// 首次执行任务前的延迟时间,可以指定一个初始的等待时间,以便在启动周期性任务之前有一定的准备时间。当前:5s
5L,
// 任务执行的周期时间,即两次连续任务开始执行之间的时间间隔。当前:5s
5L,
// 时间单位:秒
TimeUnit.SECONDS
);
}
// 扫描清理动作
private void scanAndClean() {
// Map<BeanFactory, Multimap<String, SpringValue>> registry
// 利用迭代器,清理数据
// 针对数据:Multimap<key, SpringValue> 所有BeanFactory对应的的values()
Iterator iterator = this.registry.values().iterator();
// 当前线程正常,且迭代器中有数据
while(!Thread.currentThread().isInterrupted() && iterator.hasNext()) {
// 针对数据:具体的某个beanFactory对应的:Multimap<key, SpringValue>
// 一个key:多个value,多条数据
Multimap<String, SpringValue> springValues = (Multimap)iterator.next();
// 继续迭代处理
Iterator springValueIterator = springValues.entries().iterator();
// 如果存在<key, SpringValue>数据,则继续
while(springValueIterator.hasNext()) {
// 拿到当前具体的<key, SpringValue>数据
Entry<String, SpringValue> springValue = (Entry)springValueIterator.next();
// 如果当前属性值被标记无效-失效状态(是否存在弱引用)
if (!((SpringValue)springValue.getValue()).isTargetBeanValid()) {
// 某个具体key对应的具体SpringValue,失效了,则直接清理掉
springValueIterator.remove();
}
}
}
}
}
package com.ctrip.framework.apollo;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
// 自定义了一个监听器接口(监听器模式)
public interface ConfigChangeListener {
// 监听行为
void onChange(/****/ConfigChangeEvent var1);
}
package com.ctrip.framework.apollo.spring.property;
import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.util.SpringInjector;
import com.google.gson.Gson;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.env.Environment;
import org.springframework.util.CollectionUtils;
// 具体监听器类
public class AutoUpdateConfigChangeListener implements /**自定义了一个监听器接口**/ConfigChangeListener {
// 日志
private static final Logger logger = LoggerFactory.getLogger(AutoUpdateConfigChangeListener.class);
private final boolean typeConverterHasConvertIfNecessaryWithFieldParameter = this.testTypeConverterHasConvertIfNecessaryWithFieldParameter();
// 环境对象
private final Environment environment;
// Bean工厂类
private final ConfigurableBeanFactory beanFactory;
// 类型转换器
private final TypeConverter typeConverter;
// 占位符助手
private final PlaceholderHelper placeholderHelper;
// @Value注册器(管理 Spring 属性绑定,与 Apollo 配置中心集成,处理占位符解析:)
// 与 Apollo 配置中心紧密合作,实现配置的动态更新。当 Apollo 配置中心的配置发生变化时,Apollo 客户端会通知SpringValueRegistry。
// SpringValueRegistry接收到通知后,会查找那些依赖于变化配置的@Value注解的属性,并更新其值。这确保了应用能够实时响应配置的变化,而无需重新启动。
private final SpringValueRegistry springValueRegistry;
private final Gson gson;
// 构造器注入(初始化配置)
public AutoUpdateConfigChangeListener(Environment environment, // 环境对象
ConfigurableListableBeanFactory beanFactory // spring ioc bean工厂对象
) {
// 注入当前适用的Bean工厂对象
this.beanFactory = beanFactory;
this.typeConverter = this.beanFactory.getTypeConverter();
this.environment = environment;
// 又见Injector技术
this.placeholderHelper = (PlaceholderHelper)SpringInjector.getInstance(PlaceholderHelper.class);
// apollo自定义的SpringValueRegistry
this.springValueRegistry = (SpringValueRegistry)SpringInjector.getInstance(SpringValueRegistry.class);
this.gson = new Gson();
}
// 监听器实现类-监控的动作
public void onChange(/**监控的事件内容**/ConfigChangeEvent changeEvent) {
// 拿到所有变更的数据Keys
Set<String> keys = changeEvent.changedKeys();
// 非空判定
if (!CollectionUtils.isEmpty(keys)) {
// 迭代
Iterator i$ = keys.iterator();
// 下面是while循环、do-while循环组合
while(true) {
// 预先放置一个空集合
Collection targetValues;
// go~
do {
// go~
do {
// 有后续迭代内容
if (!i$.hasNext()) {
return;
}
// 拿到具体变更的key
String key = (String)i$.next();
// 通过@Value属性注册器获取该Key的值,存放到前文预置的集合对象中
// Map<BeanFactory, Multimap<String, SpringValue>> registry = Maps.newConcurrentMap
// 注册目标对象集合:按照注册Bean工厂对象作一级区分,然后按照Key做二级区分,且目标数据为多个
targetValues = this.springValueRegistry.get(this.beanFactory, key);
// 预先放置的集合为null时,进入循环
} while(targetValues == null);
// 预先放置的集合为空集合时,进入循环
} while(targetValues.isEmpty());
// 针对“前文预置的集合对象”,获取它的迭代器
Iterator i$ = targetValues.iterator();
// 循环迭代
while(i$.hasNext()) {
// 逐个拿到当前Key对应的所有数据
SpringValue val = (SpringValue)i$.next();
// 更新数据
this.updateSpringValue(val);
}
}
}
}
// 更新属性数据
private void updateSpringValue(/**传入已经明确需要更新的属性值对象**/SpringValue springValue) {
try {
// 拆包预处理-拿到具体的数据
Object value = this.resolvePropertyValue(springValue);
// 更新操作
springValue.update(value);
logger.info("Auto update apollo changed value successfully, new value: {}, {}", value, springValue);
} catch (Throwable var3) {
logger.error("Auto update apollo changed value failed, {}", springValue.toString(), var3);
}
}
// 拆包预处理-拿到具体的数据
private Object resolvePropertyValue(SpringValue springValue) {
// 使用拆包工具(PlaceholderHelper)进行解析处理
Object value = this.placeholderHelper.resolvePropertyValue(this.beanFactory,
springValue.getBeanName(),
springValue.getPlaceholder()
);
// 格式化处理:
if (springValue.isJson()) {
// Json
value = this.parseJsonValue((String)value, springValue.getGenericType());
} else if (springValue.isField()) {
// 有属性 ???
if (this.typeConverterHasConvertIfNecessaryWithFieldParameter) {
// ???
value = this.typeConverter.convertIfNecessary(value, springValue.getTargetType(), springValue.getField());
} else {
// ???
value = this.typeConverter.convertIfNecessary(value, springValue.getTargetType());
}
} else {
// 其他
value = this.typeConverter.convertIfNecessary(value, springValue.getTargetType(), springValue.getMethodParameter());
}
return value;
}
// json格式化处理
private Object parseJsonValue(String json, Type targetType) {
try {
return this.gson.fromJson(json, targetType);
} catch (Throwable var4) {
logger.error("Parsing json '{}' to type {} failed!", new Object[]{json, targetType, var4});
throw var4;
}
}
// 类型转换测试判定
private boolean testTypeConverterHasConvertIfNecessaryWithFieldParameter() {
try {
TypeConverter.class.getMethod("convertIfNecessary", Object.class, Class.class, Field.class);
return true;
} catch (Throwable var2) {
return false;
}
}
}
现在,AutoUpdateConfigChangeListener 的具体逻辑知道了,就是监控到 apollo 配置的变动时,可以通过该类的onChange(/**监控的事件内容**/ConfigChangeEvent changeEvent)实现属性的更新。
现在还缺少一个时间触发机制和触发点?继续分析!!!
AutoUpdateConfigChangeListener.java 只是提供了自动更新字段数据的能力,因为是实时更新的,那么就是在控制从 apollo 服务端拉取数据后,都会将数据包装成CompositePropertySource 对象丢到环境对象中去
在前文中:
此处为语雀内容卡片,点击链接查看:https://www.yuque.com/xiaofengweiling/fkrpy5/heq5kl80v8m68e5w
看到注册了一堆定制的处理器
其中有一个:
// 注册PropertySourcesProcessor(属性资源处理器)核心的一个
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry,
PropertySourcesProcessor.class.getName(),
PropertySourcesProcessor.class);
接下来具体分析一下,看看里面有哪些逻辑?
package com.ctrip.framework.apollo.spring.config;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.build.ApolloInjector;
// 看到目标了
import com.ctrip.framework.apollo.spring.property.AutoUpdateConfigChangeListener;
import com.ctrip.framework.apollo.spring.util.SpringInjector;
import com.ctrip.framework.apollo.util.ConfigUtil;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.collect.UnmodifiableIterator;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
// 定制处理器
public class PropertySourcesProcessor implements
// 后置处理器
// 在 Spring 容器加载完 Bean 的定义信息,但在实例化 Bean 之前被调用
// 可以对 BeanDefinition 进行修改,比如修改 Bean 的属性值、添加新的属性等
BeanFactoryPostProcessor,
// EnvironmentAware是一个接口,实现该接口的类可以感知和访问 Spring 的Environment对象
EnvironmentAware,
PriorityOrdered
{
// apollo的NAMESPACE_NAMES
private static final Multimap<Integer, String> NAMESPACE_NAMES = LinkedHashMultimap.create();
//
private static final Set<BeanFactory> AUTO_UPDATE_INITIALIZED_BEAN_FACTORIES = Sets.newConcurrentHashSet();
//
private final ConfigPropertySourceFactory configPropertySourceFactory = (ConfigPropertySourceFactory)SpringInjector.getInstance(ConfigPropertySourceFactory.class);
// http操作对象
private final ConfigUtil configUtil = (ConfigUtil)ApolloInjector.getInstance(ConfigUtil.class);
// 环境对象
private ConfigurableEnvironment environment;
// 构造器
public PropertySourcesProcessor() {
}
//
public static boolean addNamespaces(Collection<String> namespaces, int order) {
return NAMESPACE_NAMES.putAll(order, namespaces);
}
// 前置处理器-触发逻辑
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 初始化属性装配
this.initializePropertySources();
// 触发自动话属性装配特性
this.initializeAutoUpdatePropertiesFeature(beanFactory);
}
// 初始化属性装配
private void initializePropertySources() {
// 环境中没有:“ApolloPropertySources”时
if (!this.environment.getPropertySources().contains("ApolloPropertySources")) {
// 创建一个:“ApolloPropertySources”
CompositePropertySource composite = new CompositePropertySource("ApolloPropertySources");
// 拿到apollo的NameSpaceNames数据,默认为空
ImmutableSortedSet<Integer> orders = ImmutableSortedSet.copyOf(NAMESPACE_NAMES.keySet());
// 迭代
UnmodifiableIterator iterator = orders.iterator();
// 当前默认为空,初始情况下不会触发
while(iterator.hasNext()) {
// 如果有数据
int order = (Integer)iterator.next();
Iterator i$ = NAMESPACE_NAMES.get(order).iterator();
while(i$.hasNext()) {
// 拿到namespace
String namespace = (String)i$.next();
// 获取当前apollo中namespace环境数据,主动拉取一次数据
Config config = ConfigService.getConfig(namespace);
// 数据转换&装配处理
composite.addPropertySource(this.configPropertySourceFactory.getConfigPropertySource(namespace, config));
}
}
// 清理:“拿到apollo的NameSpaceNames数据”
NAMESPACE_NAMES.clear();
// 服务启动时,主动从apollo服务端获取的配置数据,被打包在这个对象中了
// 创建一个组合属性对象
// CompositePropertySource composite = new CompositePropertySource("ApolloBootstrapPropertySources");
// 检测到环境中有“ApolloBootstrapPropertySources”配置
if (this.environment.getPropertySources().contains("ApolloBootstrapPropertySources")) {
// 如果存在
// 确保Bootstrap属性优先级
this.ensureBootstrapPropertyPrecedence(this.environment);
// 把“ApolloPropertySources”加到环境属性源中仅次于“ApolloBootstrapPropertySources”的位置
// “ApolloBootstrapPropertySources”是被以首位的形式加入的
// 所以“ApolloPropertySources”排在第二位
this.environment.getPropertySources().addAfter("ApolloBootstrapPropertySources", composite);
} else {
// 如果不存在
// 把“ApolloPropertySources”加到环境属性源的首位
this.environment.getPropertySources().addFirst(composite);
}
}
}
// 确保Bootstrap属性优先级
private void ensureBootstrapPropertyPrecedence(ConfigurableEnvironment environment) {
// 拿到所有环境属性源数据
MutablePropertySources propertySources = environment.getPropertySources();
// 获取当前“ApolloBootstrapPropertySources”中的属性数据
PropertySource<?> bootstrapPropertySource = propertySources.get("ApolloBootstrapPropertySources");
// 存在 且 非首位,说明出现了问题(按照前文的逻辑:“ApolloBootstrapPropertySources”必须在首位)
if (bootstrapPropertySource != null && propertySources.precedenceOf(bootstrapPropertySource) != 0) {
// 清理异常配置
propertySources.remove("ApolloBootstrapPropertySources");
// 矫正位置,重新放置在首位
propertySources.addFirst(bootstrapPropertySource);
}
}
// 触发自动话属性装配特性
private void initializeAutoUpdatePropertiesFeature(ConfigurableListableBeanFactory beanFactory) {
// 是否启用配置:“apollo.autoUpdateInjectedSpringProperties” 默认为true
// 将当前的ioc加载Bean的beanFactory,收集起来
if (this.configUtil.isAutoUpdateInjectedSpringPropertiesEnabled() && AUTO_UPDATE_INITIALIZED_BEAN_FACTORIES.add(beanFactory)) {
// 创建一个监听器对象,完成监听器初始化
AutoUpdateConfigChangeListener autoUpdateConfigChangeListener = new AutoUpdateConfigChangeListener(
this.environment, // 当前环境
beanFactory // 当前bean工厂对象
);
// 拿到所有apollo配置数据
List<ConfigPropertySource> configPropertySources = this.configPropertySourceFactory.getAllConfigPropertySources();
// 迭代
Iterator i$ = configPropertySources.iterator();
while(i$.hasNext()) {
// 具体的ConfigPropertySource
ConfigPropertySource configPropertySource = (ConfigPropertySource)i$.next();
// 为每一个属性添加监听器
// ((Config)this.source).addChangeListener(listener); 所有的监听器都是加装在具体的Config配置对象上了
// Config是一个接口,具体的实现子类为:
// 添加了监听器之后,还需要找到监听器的使用触发点在哪里???
configPropertySource.addChangeListener(autoUpdateConfigChangeListener);
}
}
}
// 设置环境
public void setEnvironment(Environment environment) {
this.environment = (ConfigurableEnvironment)environment;
}
// 拿到排序ID
public int getOrder() {
return -2147483648;
}
// 重置
static void reset() {
NAMESPACE_NAMES.clear();
AUTO_UPDATE_INITIALIZED_BEAN_FACTORIES.clear();
}
}
继续分析一下
// 为每一个属性添加监听器
// ((Config)this.source).addChangeListener(listener); 所有的监听器都是加装在具体的Config配置对象上了
// Config是一个接口,具体的实现子类为:
// 添加了监听器之后,还需要找到监听器的使用触发点在哪里???
configPropertySource.addChangeListener(autoUpdateConfigChangeListener);
package com.ctrip.framework.apollo;
import com.ctrip.framework.apollo.enums.ConfigSourceType;
import com.google.common.base.Function;
import java.util.Date;
import java.util.Locale;
import java.util.Set;
public interface Config {
......
void addChangeListener(ConfigChangeListener var1);
void addChangeListener(ConfigChangeListener var1, Set<String> var2);
void addChangeListener(ConfigChangeListener var1, Set<String> var2, Set<String> var3);
boolean removeChangeListener(ConfigChangeListener var1);
......
}
看一下AbstractConfig.java
package com.ctrip.framework.apollo.internals;
......
public abstract class AbstractConfig implements Config {
private static final Logger logger = LoggerFactory.getLogger(AbstractConfig.class);
// 任务线程执行器
private static final ExecutorService m_executorService = Executors.newCachedThreadPool(ApolloThreadFactory.create("Config", true));
// 维护这所有的监听器
private final List<ConfigChangeListener> m_listeners = Lists.newCopyOnWriteArrayList();
// 监听器的Keys
private final Map<ConfigChangeListener, Set<String>> m_interestedKeys = Maps.newConcurrentMap();
// 监听器的KeyPrefixes
private final Map<ConfigChangeListener, Set<String>> m_interestedKeyPrefixes = Maps.newConcurrentMap();
// apollo配置数据工具
private final ConfigUtil m_configUtil = (ConfigUtil)ApolloInjector.getInstance(ConfigUtil.class);
// 各种缓存
private volatile Cache<String, Integer> m_integerCache;
private volatile Cache<String, Long> m_longCache;
private volatile Cache<String, Short> m_shortCache;
private volatile Cache<String, Float> m_floatCache;
private volatile Cache<String, Double> m_doubleCache;
private volatile Cache<String, Byte> m_byteCache;
private volatile Cache<String, Boolean> m_booleanCache;
private volatile Cache<String, Date> m_dateCache;
private volatile Cache<String, Long> m_durationCache;
private final Map<String, Cache<String, String[]>> m_arrayCache = Maps.newConcurrentMap();
private final List<Cache> allCaches = Lists.newArrayList();
private final AtomicLong m_configVersion = new AtomicLong();
// 属性工厂对象
protected PropertiesFactory propertiesFactory = (PropertiesFactory)ApolloInjector.getInstance(PropertiesFactory.class);
public AbstractConfig() {
}
......
// 绑定监听器
public void addChangeListener(ConfigChangeListener listener) {
this.addChangeListener(listener, (Set)null);
}
// 绑定监听器
public void addChangeListener(ConfigChangeListener listener, Set<String> interestedKeys) {
this.addChangeListener(listener, interestedKeys, (Set)null);
}
// 绑定监听器
public void addChangeListener(ConfigChangeListener listener, Set<String> interestedKeys, Set<String> interestedKeyPrefixes) {
if (!this.m_listeners.contains(listener)) {
this.m_listeners.add(listener);
if (interestedKeys != null && !interestedKeys.isEmpty()) {
this.m_interestedKeys.put(listener, Sets.newHashSet(interestedKeys));
}
if (interestedKeyPrefixes != null && !interestedKeyPrefixes.isEmpty()) {
this.m_interestedKeyPrefixes.put(listener, Sets.newHashSet(interestedKeyPrefixes));
}
}
}
// 移除监听器
public boolean removeChangeListener(ConfigChangeListener listener) {
this.m_interestedKeys.remove(listener);
this.m_interestedKeyPrefixes.remove(listener);
return this.m_listeners.remove(listener);
}
......
// 监听器的触发动作
protected void fireConfigChange(final ConfigChangeEvent changeEvent) {
Iterator i$ = this.m_listeners.iterator();
while(i$.hasNext()) {
// 拿到具体的监听器
final ConfigChangeListener listener = (ConfigChangeListener)i$.next();
// 检测方法(异常和安全检测,放置误操作等等,此处不再深究了)
if (this.isConfigChangeListenerInterested(listener, changeEvent)) {
// 任务线程
m_executorService.submit(
// 具体任务逻辑
new Runnable() {
public void run() {
String listenerName = listener.getClass().getName();
Transaction transaction = Tracer.newTransaction("Apollo.ConfigChangeListener", listenerName);
try {
// ===》触发监听器核心逻辑《===
listener.onChange(changeEvent);
transaction.setStatus("0");
} catch (Throwable var7) {
transaction.setStatus(var7);
Tracer.logError(var7);
AbstractConfig.logger.error("Failed to invoke config change listener {}", listenerName, var7);
} finally {
transaction.complete();
}
}
});
}
}
}
......
}
问题继续存在,AbstractConfig.fireConfigChange 方法是在哪里被触发的呢?
Config.java --> AbstractConfig --> DefaultConfig.java
基于这个关系脉络,继续分析!!!
......
public class DefaultConfig extends AbstractConfig implements RepositoryChangeListener {
private static final Logger logger = LoggerFactory.getLogger(DefaultConfig.class);
private final String m_namespace;
private final Properties m_resourceProperties;
private final AtomicReference<Properties> m_configProperties;
private final ConfigRepository m_configRepository;
private final RateLimiter m_warnLogRateLimiter;
private volatile ConfigSourceType m_sourceType;
public DefaultConfig(String namespace, ConfigRepository configRepository) {
this.m_sourceType = ConfigSourceType.NONE;
this.m_namespace = namespace;
this.m_resourceProperties = this.loadFromResource(this.m_namespace);
this.m_configRepository = configRepository;
this.m_configProperties = new AtomicReference();
this.m_warnLogRateLimiter = RateLimiter.create(0.017D);
this.initialize();
}
private void initialize() {
try {
this.updateConfig(this.m_configRepository.getConfig(), this.m_configRepository.getSourceType());
} catch (Throwable var5) {
Tracer.logError(var5);
logger.warn("Init Apollo Local Config failed - namespace: {}, reason: {}.", this.m_namespace, ExceptionUtil.getDetailMessage(var5));
} finally {
this.m_configRepository.addChangeListener(this);
}
}
// 收集监听器需要的参数:
private Map<String, ConfigChange> updateAndCalcConfigChanges(Properties newConfigProperties,
ConfigSourceType sourceType) {
// 根据当前的:m_namespace + newConfigProperties.stringPropertyNames()即Key,收集对应的所有的变动List<ConfigChange>数据
List<ConfigChange> configChanges = this.calcPropertyChanges(this.m_namespace,
(Properties)this.m_configProperties.get(),
newConfigProperties);
// 构建真实变动容器
Builder<String, ConfigChange> actualChanges = new Builder();
Iterator i$ = configChanges.iterator();
// 创建一个变动对象
ConfigChange change;
while(i$.hasNext()) {
change = (ConfigChange)i$.next();
// 为每一个变动对象写入旧属性值
change.setOldValue(
this.getProperty(
change.getPropertyName(),
change.getOldValue()
)
);
// 后文中
}
this.updateConfig(newConfigProperties, sourceType);
this.clearConfigCache();
// 迭代所有变动数据
i$ = configChanges.iterator();
while(i$.hasNext()) {
change = (ConfigChange)i$.next();
// 为每一个变动对象写入新的值
change.setNewValue(this.getProperty(change.getPropertyName(), change.getNewValue()));
// 根据变动类型,分发处理
switch(change.getChangeType()) {
// 新增
case ADDED:
// 新旧数据不同,有变动
if (!Objects.equals(change.getOldValue(), change.getNewValue())) {
if (change.getOldValue() != null) {
change.setChangeType(PropertyChangeType.MODIFIED);
}
// 收集
actualChanges.put(change.getPropertyName(), change);
}
break;
// 修改
case MODIFIED:
// 新旧数据不同,有变动
if (!Objects.equals(change.getOldValue(), change.getNewValue())) {
// 收集
actualChanges.put(change.getPropertyName(), change);
}
break;
// 删除
case DELETED:
// 新旧数据不同,有变动
if (!Objects.equals(change.getOldValue(), change.getNewValue())) {
if (change.getNewValue() != null) {
change.setChangeType(PropertyChangeType.MODIFIED);
}
// 收集
actualChanges.put(change.getPropertyName(), change);
}
}
}
// 拿到收集到的数据返回
return actualChanges.build();
}
......
// 线程安全:
public synchronized void onRepositoryChange(
/**命名空间**/String namespace,
/**新的属性数据**/ Properties newProperties
) {
// 检测到新旧属性不一致,认为是发生了变化
if (!newProperties.equals(this.m_configProperties.get())) {
// 拿到配置属性类型
ConfigSourceType sourceType = this.m_configRepository.getSourceType();
// 创建一个新的属性
Properties newConfigProperties = this.propertiesFactory.getPropertiesInstance();
// 装配数据到新属性对象中
newConfigProperties.putAll(newProperties);
// 收集监听器需要的参数:
// namespace = m_namespace
// actualChanges中的变动对象,设置了新的值和旧的值,使得数据完整了
Map<String, ConfigChange> actualChanges = this.updateAndCalcConfigChanges(newConfigProperties, sourceType);
if (!actualChanges.isEmpty()) {
// 触发事件,引起监听器的注意,从而实现属性更新
this.fireConfigChange(new ConfigChangeEvent(this.m_namespace, actualChanges));
Tracer.logEvent("Apollo.Client.ConfigChanges", this.m_namespace);
}
}
}
......
}
继续向上找DefaultConfig.onRepositoryChange 方法的出发点在哪里~!!!
public synchronized void onRepositoryChange(
/**命名空间**/String namespace,
/**新的属性数据**/ Properties newProperties
) {}
onRepositoryChange 方法,一看就是针对Repository 类型的 change 监听的。
再梳理一下依赖关系:
Config.java --> AbstractConfig --> DefaultConfig.java
public class DefaultConfig
extends AbstractConfig
implements RepositoryChangeListener
DefaultConfig.java --> RepositoryChangeListener.java
发现: AbstractConfigRepository.java 中有维护监听器的触发机制:
其中维护了一个监听器的池子:
private List<RepositoryChangeListener> m_listeners;
说明一下:
RepositoryChangeListener.java 是一个接口,
DefaultConfig.java 是一个实现类,实现了 RepositoryChangeListener.java 接口
所以
private List<RepositoryChangeListener> m_listeners 中是可以存放DefaultConfig.java 对象的,(基本的装箱拆箱原则)
public class RemoteConfigRepository
extends AbstractConfigRepository
e
可以知道:
this.fireRepositoryChange(this.m_namespace, this.getConfig());
其中:
this.getConfig()拿到的数据就是上一行:this.m_configCache.set(current);中的 current 对象:
而 current 对象就是DefaultConfig 类型
详情可以查看:
此处为语雀内容卡片,点击链接查看:https://www.yuque.com/xiaofengweiling/fkrpy5/ltzdv77vbvrzdi06
所以破案了:
-----------------------------------------------------------------------------
总结一下:
(1)在前置处理器中:PropertySourcesProcessor.java 为每一个属性绑定监听器:AutoUpdateConfigChangeListener
(2)在服务启动时(主动向 apollo 服务端拉取一次)和定期刷新(定期拉取)时触发的 sync()方法中,主动触发onRepositoryChange()方法,详细流程如下:
- RemoteConfigRepository.java:
-
- this.fireRepositoryChange(this.m_namespace, this.getConfig());
- AbstractConfigRepository.java:
-
- fireRepositoryChange(String namespace, Properties newProperties);
- DefaultConfig.java:
-
- onRepositoryChange(String namespace, Properties newProperties);
- AbstractConfig.java
-
- fireConfigChange(final ConfigChangeEvent changeEvent)