Apollo源码阅读笔记(一)

先来一张官方客户端设计图,方便我们了解客户端的整体思路。

我们在使用Apollo的时候,需要标记@EnableApolloConfig来告诉程序开启apollo配置,所以这里就以EnableApolloConfig为入口,来看下apollo客户端的实现逻辑。关于apollo的使用方法详见 这里

1. 入口 @EnableApolloConfig 注解

@EnableApolloConfig(value={"application","test-yejg"})

默认的namespace是application;

通过@EnableApolloConfig注解,引入了ApolloConfigRegistrar

public class ApolloConfigRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(EnableApolloConfig.class.getName()));
String[] namespaces = attributes.getStringArray("value");
int order = attributes.getNumber("order");
// 暂存需要关注的namespaces,后面在PropertySourcesProcessor中会把配置属性加载env中
PropertySourcesProcessor.addNamespaces(Lists.newArrayList(namespaces), order); Map<String, Object> propertySourcesPlaceholderPropertyValues = new HashMap<>();
// to make sure the default PropertySourcesPlaceholderConfigurer's priority is higher than PropertyPlaceholderConfigurer
propertySourcesPlaceholderPropertyValues.put("order", 0);
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class.getName(), PropertySourcesPlaceholderConfigurer.class, propertySourcesPlaceholderPropertyValues); BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesProcessor.class.getName(), PropertySourcesProcessor.class);
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloAnnotationProcessor.class.getName(), ApolloAnnotationProcessor.class);
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueProcessor.class.getName(), SpringValueProcessor.class);
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueDefinitionProcessor.class.getName(), SpringValueDefinitionProcessor.class);
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloJsonValueProcessor.class.getName(), ApolloJsonValueProcessor.class);
}
}

注意上面代码中,通过PropertySourcesProcessor.addNamespaces暂存了namespaces,下面就先沿着 PropertySourcesProcessor来展开

2. 配置设置到environment的过程

PropertySourcesProcessor实现了BeanFactoryPostProcessor,并能获取到env

public class PropertySourcesProcessor implements BeanFactoryPostProcessor, EnvironmentAware, PriorityOrdered{
...
}

在Spring应用启动的时候

refresh() –> invokeBeanFactoryPostProcessors(beanFactory) –> PropertySourcesProcessor.postProcessBeanFactory

—> initializePropertySources();

—> initializeAutoUpdatePropertiesFeature(beanFactory);

就这样,Apollo的PropertySourcesProcessor就被调用起来了。

在它的postProcessBeanFactory方法中依次调用initializePropertySources和initializeAutoUpdatePropertiesFeature,先来看initializePropertySources做了啥事情:

  1. 将NAMESPACE_NAMES (Multimap<Integer, String>)排序;

  2. 遍历排序后的namespaces,依次调用 ConfigService.getConfig(namespace) 获取配置信息Config;

  3. 将config封装成ConfigPropertySource[Apollo的],保存到CompositePropertySource[spring-core的];

    ​ 此composite名为 ApolloPropertySources

    ​ ConfigPropertySource继承自spring-core的EnumerablePropertySource

    ​ 代码:composite.addPropertySource(XXX);

  4. 循环处理完 NAMESPACE_NAMES 之后,将其清空掉;

  5. 将前面循环处理好的compositePropertySource加入到env中;

    ​ 加到env时,判断env中是否存在 ApolloBootstrapPropertySources是否存在,确保其在第一的位置,而前面循环处理得到的ApolloPropertySources紧随其后。

    ​ 相关代码:

    ​ environment.getPropertySources().addAfter(“XXX source name”, composite);

    ​ environment.getPropertySources().addFirst(composite);

这部分的逻辑,其实就是佐证了Apollo的设计思路

盗用官方的一张图来简单说明这个流程:

最新文章

  1. 提升网速的路由器优化方法(UPnP、QoS、MTU、交换机模式、无线中继)
  2. 重视blog备份——兼记我与CSDN的爱恨情仇
  3. Devexpress DateEdit控件的值不反馈到数据源的处理方式。
  4. IOS一些高效的第三方框架库
  5. git命令笔记
  6. 简明python教程 --C++程序员的视角(一):数值类型、字符串、运算符和控制流
  7. JasperReports教程:Report Data Sources
  8. 食物链 poj 1182
  9. HDU(3605),二分图多重匹配
  10. Altium Designer哪里下载和导入元件库_图文教程
  11. [转]mysql 导入导出数据库以及函数、存储过程的介绍
  12. js推断元素是否隐藏
  13. Wolf and Rabbit(gcd)
  14. OvS: data structure analysis
  15. JDK、JRE、JVM详解
  16. ORA-279 signalled during: alter database recover logfile
  17. logback日志框架的简单使用
  18. Git 如何解决部署远程仓库出现 fatal: refusing to merge unrelated histories 问题
  19. php_network_getaddresses: getaddrinfo failed 原因
  20. c#线程2

热门文章

  1. Note of Python Turtle
  2. 【git 报错】Could not read from remote repository.Please make sure you have the correct access rights.
  3. 背水一战 Windows 10 (92) - 文件系统: 读写“最近访问列表”和“未来访问列表”, 管理以及使用索引
  4. 微信小程序:scroll滑到指定位置
  5. MySQL学习笔记2(多表操作)
  6. Dispatch Queue 之 dispatch_sync
  7. Spring Boot Starters启动器
  8. Maven 如何发布 jar 包到 Nexus 私库
  9. 干货:教你如何监控 Java 线程池运行状态
  10. 解决tomcat启动慢问题