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的設計思路

盜用官方的一張圖來簡單說明這個流程:

相關文章
相關標籤/搜索