【Apollo】Apollo 配置首次加载过程

发布时间 2023-08-29 08:16:25作者: 酷酷-

1  前言

今天我们来看看 Apollo的东西,比如我们的项目引入了 Apollo,那么我们的服务启动的时候,会首先从Apollo读取配置那么它是怎么做的呢,这节我们就来瞅瞅。

Apollo版本:1.7

大家可以自己去下载安装一个哈,方便自己调试,边看边调试可以有个更好的理解哈。

2  源码分析

2.1  @EnableApolloConfig 入口

首先 apollo引入后,大概会引进两块的内容,一块是client包,一块是它的核心包。并且每个包下边有SPI的类或者 spring.factories,这两类东西应该很敏感哈,SPI他会加载你的类,spring.factories是spring会加载的类。我看了他们引进的类,没什么特别特殊的地方,真正在我们的服务启动的时候去加载配置的还是 @EnableApolloConfig 注解为入口的。

我们看看 @EnableApolloConfig 引进的类:ApolloConfigRegistrar,从名字上看就可以理解他是 Apollo的配置注册类。我们继续进入看看:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(ApolloConfigRegistrar.class)
public @interface EnableApolloConfig {
  /**
   * Apollo namespaces to inject configuration into Spring Property Sources.
   */
  String[] value() default {ConfigConsts.NAMESPACE_APPLICATION};

  /**
   * The order of the apollo config, default is {@link Ordered#LOWEST_PRECEDENCE}, which is Integer.MAX_VALUE.
   * If there are properties with the same name in different apollo configs, the apollo config with smaller order wins.
   * @return
   */
  int order() default Ordered.LOWEST_PRECEDENCE;
}

这里我简单串一下 ApolloConfigRegistrar 的执行来源过程哈,来源于 spring 中的BeanDefinitionRegistryPostProcessors,继而通过 ConfigurationClassPostProcessor 后置处理,筛选出 ImportBeanDefinitionRegistrar 配置类,进行注册。如下图:

2.2  ApolloConfigRegistrar 

那我们来看看 ApolloConfigRegistrar,它是交给 ApolloConfigRegistrarHelper 来注册一些 bean的,这种写法大家平时写代码也可以参考参考,相当于把逻辑交给一个对象专门来处理,下沉一层,方便扩展,各司其职,我们看看:

public class ApolloConfigRegistrar implements ImportBeanDefinitionRegistrar {

  private ApolloConfigRegistrarHelper helper = ServiceBootstrap.loadPrimary(ApolloConfigRegistrarHelper.class);

  @Override
  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    helper.registerBeanDefinitions(importingClassMetadata, registry);
  }
}
public class DefaultApolloConfigRegistrarHelper implements ApolloConfigRegistrarHelper {

  @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");
    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);
  }

  @Override
  public int getOrder() {
    return Ordered.LOWEST_PRECEDENCE;
  }
}

可以看到注册器,引进了一堆后置处理器,那么我们的配置在 Apollo 的配置是由谁去加载的呢?其实就是 PropertySourcesProcessor 属性源。

2.3  PropertySourcesProcessor 

我们看看 PropertySourcesProcessor 获取配置的一个过程:

获取完配置信息后,把它封装进了 CompositePropertySource 属性源里,并放进了环境变量里,这样我们的Bean在初始化的时候,是不是就赋值啦。

3  小结

好啦,本节我们主要是看一下 Apollo 获取配置的入口过程哈,有理解不对的地方欢迎指正哈。