Apollo源码阅读笔记(一)

Apollo源码阅读笔记(一)

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

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

1. 入口 @EnableApolloConfig 注解

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

默认的namespace是application;
经过@EnableApolloConfig注解,引入了ApolloConfigRegistrargithub

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来展开spring

2. 配置设置到environment的过程

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

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

在Spring应用启动的时候ide

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

—> initializePropertySources();spa

—> initializeAutoUpdatePropertiesFeature(beanFactory);设计

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

在它的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的设计思路

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

相关文章
相关标签/搜索