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

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

  • 相关阅读:
    kill eclipse
    C语言之表达式运算整体提升
    查找函数对比:findall,search,match
    Linux backtrace()
    git本地协同
    git 撤销push到服务器的代码
    gtest
    C陷阱篇之enum默认长度
    程序员中文开发者手册
    C语言错题分析
  • 原文地址:https://www.cnblogs.com/yejg1212/p/10232871.html
Copyright © 2020-2023  润新知