Apollo源码阅读(三)Apollo客户端-ApolloApplicationContextInitializer

1,194 阅读1分钟

一、spring.factories

org.springframework.context.ApplicationContextInitializer=\
com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer
org.springframework.boot.env.EnvironmentPostProcessor=\
com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer

二、ApolloApplicationContextInitializer何时执行初始化

Initialize Apollo Configurations Just after environment is ready.

  • 实现EnvironmentPostProcessor接口的initialize方法,可以当图1执行初始化
  • 实现ApplicationContextInitializer接口的postProcessEnvironment方法,可以当图2执行初始化

  • 具体执行初始化的地方,取决于apollo.bootstrap.eagerLoad.enabled,如果为true,走图1,否则走图2。一般来说把日志级别托管在Apollo中是个常见的需求,所以一般配置apollo.bootstrap.eagerLoad.enabled=true。initialize(environment)这个方法保证只会执行一次。
 @Override
  public void initialize(ConfigurableApplicationContext context) {
    ConfigurableEnvironment environment = context.getEnvironment();
    // 1. 加载Apollo配置
    initialize(environment);
  }
 @Override
  public void postProcessEnvironment(ConfigurableEnvironment configurableEnvironment, SpringApplication springApplication) {
    // 1. 把StandardEnvironment里的配置塞入SystemProperties
    // 包括”app.id”,”apollo.cluster",”apollo.cacheDir",”apollo.accesskey.secret",”apollo.meta",”apollo.property.order.enable"
    initializeSystemProperty(configurableEnvironment);
    // 2. 如果apollo.bootstrap.eagerLoad.enabled=true使Apollo的加载顺序放到日志系统加载之前
    Boolean eagerLoadEnabled = configurableEnvironment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_EAGER_LOAD_ENABLED, Boolean.class, false);
    if (!eagerLoadEnabled) {
      return;
    }
    initialize(configurableEnvironment);
  }

三、ApolloApplicationContextInitializer初始化

 protected void initialize(ConfigurableEnvironment environment) {
    // 1. 判断是否已经加载了配置,如果已经加载就返回
    if (environment.getPropertySources().contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
      return;
    }
    // 2. 从Environment获取namespace列表,如果为空,默认使用application
    String namespaces = environment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_NAMESPACES, ConfigConsts.NAMESPACE_APPLICATION);
    List<String> namespaceList = NAMESPACE_SPLITTER.splitToList(namespaces);
    // CompositePropertySource是PropertySources的一个实现,包含了多个namespace的配置信息
    CompositePropertySource composite = new CompositePropertySource(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME);
    for (String namespace : namespaceList) {
      // 3、根据名称空间获取配置
      Config config = ConfigService.getConfig(namespace); 
      composite.addPropertySource(configPropertySourceFactory.getConfigPropertySource(namespace, config));
    }
    // 4、放入AbstractEnvironment.propertySources
    // 当doCreateBean的AbstractAutowireCapableBeanFactory.populateBean阶段注入    
    // 最终在PropertySourcesPropertyResolver.getProperty获取配置 
    environment.getPropertySources().addFirst(composite);
  }