一、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);
}