bootstrap的上下文创建:
SpringApplication.java:run
----->prepareEnvironment
----->EventPublishingRunListener发送ApplicationEnvironmentPreparedEvent事件
----->BootstrapApplicationListener接收事件,调用onApplicationEvent方法(事件机制)
----->bootstrapServiceContext创建bootstrap的context
context = bootstrapServiceContext(environment, event.getSpringApplication(),
configName);
在run方法里面,执行prepareEnvironment,通过事件机制(这里是同步机制),bootstrapServiceContext方法,创建bootstrap的上下文。bootstrap的上下文是AnnotationConfigApplicationContext类型的。通过这个,去解析bootstrap的配置文件。并且设置为App上下文的parent。
// Make the bootstrap context a parent of the app context
addAncestorInitializer(application, context);
为了避免执行上下文run方法的时候,再次创建新的上下文。
if (environment.getPropertySources().contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
return;
}
bootstrap的上下文在启动的过程中,去加载nacos服务端的配置信息。
具体流程是这样的:
获取配置过程:
------->1、SpringApplication.java:run方法(spring-boot.jar)
------->2、SpringApplication.java:prepareContext方法(spring-boot.jar)
------->3、SpringApplication.java:applyInitializers方法(spring-boot.jar)
------->4、PropertySourceBootstrapConfiguration.java:initialize方法(spring-cloud-context.jar)
------->5、NacosPropertySourceLocator.java:locateCollection方法(spring-cloud-starter-alibaba-nacos-config.jar)
------->6、NacosPropertySourceLocator.java:locate方法(spring-cloud-starter-alibaba-nacos-config.jar)
------->7、NacosPropertySourceLocator.java:loadApplicationConfiguration方法(spring-cloud-starter-alibaba-nacos-config.jar)
------->8、NacosPropertySourceLocator.java:loadNacosDataIfPresent方法(spring-cloud-starter-alibaba-nacos-config.jar)
------->9、NacosPropertySourceLocator.java:loadNacosPropertySource方法(spring-cloud-starter-alibaba-nacos-config.jar)
------->10、NacosPropertySourceBuilder.java:build方法(spring-cloud-starter-alibaba-nacos-config.jar)
------->11、NacosPropertySourceBuilder.java:loadNacosData方法(spring-cloud-starter-alibaba-nacos-config.jar)
------->12、NacosConfigService.java:getConfig方法(nacos-client.jar)
------->13、NacosConfigService.java:getConfigInner方法(nacos-client.jar)
------->14、ClientWorker.java:getServerConfig方法(nacos-client.jar)
第4步说明:
PropertySourceBootstrapConfiguration实现了ApplicationContextInitializer接口。使用ApplicationContextInitializer机制实现了扩展。PropertySourceBootstrapConfiguration是通过解析spring-cloud-context.jar包里面的spring.factories文件获得的。
# Bootstrap components
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration,\
org.springframework.cloud.bootstrap.encrypt.EncryptionBootstrapConfiguration,\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.cloud.util.random.CachedRandomPropertySourceAutoConfiguration
getSpringFactoriesInstances读取并解析jar包下的spring.factories配置文件:
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
注册listener的过程:
------->1、SpringApplication.java:run方法(spring-boot.jar)
------->2、SpringApplicationRunListeners.java:running方法(spring-boot.jar)
------->3、EventPublishingRunListener.java:running方法(spring-boot.jar)
------->4、AnnotationConfigServletWebServerApplicationContext.java:publishEvent方法(spring-context.jar)
------->5、AnnotationConfigServletWebServerApplicationContext.java:publishEvent方法(spring-context.jar)
------->6、SimpleApplicationEventMulticaster.java:multicastEvent方法(spring-context.jar) listener:NacosContextRefresher
------->7、SimpleApplicationEventMulticaster.java:invokeListener方法(spring-context.jar)
------->8、SimpleApplicationEventMulticaster.java:doInvokeListener方法(spring-context.jar)
------->9、NacosContextRefresher.java:onApplicationEvent方法(spring-cloud-starter-alibaba-nacos-config.jar)
------->10、NacosContextRefresher.java:registerNacosListenersForApplications方法(spring-cloud-starter-alibaba-nacos-config.jar)
------->11、NacosContextRefresher.java:registerNacosListener方法(spring-cloud-starter-alibaba-nacos-config.jar)
------->12、NacosConfigService.java:addListener方法(nacos-client.jar)
------->13、ClientWorker.java:addTenantListeners方法(nacos-client.jar)
入口,run方法:
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
通过事件机制完成listener的注册,发送的事件是ApplicationReadyEvent。接收器是NacosContextRefresher,实现了ApplicationListener接口。在回调方法onApplicationEvent中,实现对listener的注册。
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
// many Spring context
if (this.ready.compareAndSet(false, true)) {
this.registerNacosListenersForApplications();
}
}
参考:
https://zhuanlan.zhihu.com/p/63007278
https://www.cnblogs.com/duanxz/p/11239291.html
说明:
spring-cloud-context版本是2.2.3.