private ConfigurableApplicationContext bootstrapServiceContext( ConfigurableEnvironment environment, final SpringApplication application, String configName){ // 创建 bootstrap 级别的 environment StandardEnvironment bootstrapEnvironment = new StandardEnvironment(); // 将初始化生成的一些 PropertySource 移除,包括 systemProperties(JVM级的环境变量) 和 systemEnvironment(操作系统级的环境变量) MutablePropertySources bootstrapProperties = bootstrapEnvironment .getPropertySources(); for (PropertySource<?> source : bootstrapProperties) { bootstrapProperties.remove(source.getName()); } // 是否存在外部配置文件 String configLocation = environment .resolvePlaceholders("${spring.cloud.bootstrap.location:}"); String configAdditionalLocation = environment .resolvePlaceholders("${spring.cloud.bootstrap.additional-location:}"); // 初始化容器参数 Map<String, Object> bootstrapMap = new HashMap<>(); bootstrapMap.put("spring.config.name", configName); // if an app (or test) uses spring.main.web-application-type=reactive, bootstrap // will fail // force the environment to use none, because if though it is set below in the // builder // the environment overrides it bootstrapMap.put("spring.main.web-application-type", "none"); if (StringUtils.hasText(configLocation)) { bootstrapMap.put("spring.config.location", configLocation); } if (StringUtils.hasText(configAdditionalLocation)) { bootstrapMap.put("spring.config.additional-location", configAdditionalLocation); } // 将 environment 的配置添加到新增的 bootstrapEnvironment bootstrapProperties.addFirst( new MapPropertySource(BOOTSTRAP_PROPERTY_SOURCE_NAME, bootstrapMap)); for (PropertySource<?> source : environment.getPropertySources()) { if (source instanceof StubPropertySource) { continue; } bootstrapProperties.addLast(source); } // 构建了一个新的 SpringApplication SpringApplicationBuilder builder = new SpringApplicationBuilder() .profiles(environment.getActiveProfiles()).bannerMode(Mode.OFF) .environment(bootstrapEnvironment) // Don't use the default properties in this builder .registerShutdownHook(false).logStartupInfo(false) .web(WebApplicationType.NONE); final SpringApplication builderApplication = builder.application(); if (builderApplication.getMainApplicationClass() == null) { // gh_425: // SpringApplication cannot deduce the MainApplicationClass here // if it is booted from SpringBootServletInitializer due to the // absense of the "main" method in stackTraces. // But luckily this method's second parameter "application" here // carries the real MainApplicationClass which has been explicitly // set by SpringBootServletInitializer itself already. builder.main(application.getMainApplicationClass()); } if (environment.getPropertySources().contains("refreshArgs")) { // If we are doing a context refresh, really we only want to refresh the // Environment, and there are some toxic listeners (like the // LoggingApplicationListener) that affect global static state, so we need a // way to switch those off. builderApplication .setListeners(filterListeners(builderApplication.getListeners())); } // 添加 BootstrapImportSelectorConfiguration 配置类 builder.sources(BootstrapImportSelectorConfiguration.class); // 调用 SpringApplication 的run方法 final ConfigurableApplicationContext context = builder.run(); // gh-214 using spring.application.name=bootstrap to set the context id via // `ContextIdApplicationContextInitializer` prevents apps from getting the actual // spring.application.name // during the bootstrap phase. context.setId("bootstrap"); // Make the bootstrap context a parent of the app context // 配置 bootstrap 作为 application 的父容器 addAncestorInitializer(application, context); // It only has properties in it now that we don't want in the parent so remove // it (and it will be added back later) bootstrapProperties.remove(BOOTSTRAP_PROPERTY_SOURCE_NAME); // 配置合并 mergeDefaultProperties(environment.getPropertySources(), bootstrapProperties); return context; }
publicvoidonApplicationEvent(ApplicationEnvironmentPreparedEvent event){ //省略... // don't listen to events in a bootstrap context if (environment.getPropertySources().contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) { return; } //省略... }