Apollo源碼閱讀筆記(一)


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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM