private ConfigurableApplicationContext bootstrapServiceContext( ConfigurableEnvironment environment, final SpringApplication application, String configName) { StandardEnvironmentbootstrapEnvironment=newStandardEnvironment(); MutablePropertySourcesbootstrapProperties= bootstrapEnvironment .getPropertySources(); for (PropertySource<?> source : bootstrapProperties) { bootstrapProperties.remove(source.getName()); } StringconfigLocation= environment .resolvePlaceholders("${spring.cloud.bootstrap.location:}"); StringconfigAdditionalLocation= environment .resolvePlaceholders("${spring.cloud.bootstrap.additional-location:}"); Map<String, Object> bootstrapMap = newHashMap<>(); 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
// 如果一个应用(或者 test)使用 spring.main.web-application-type=reactive,bootstrap 就会失败 // 强制环境使用 none,因为如果在构建器中设置为 below,环境就会覆盖??? 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); } bootstrapProperties.addFirst( newMapPropertySource(BOOTSTRAP_PROPERTY_SOURCE_NAME, bootstrapMap)); for (PropertySource<?> source : environment.getPropertySources()) { if (source instanceof StubPropertySource) { continue; } bootstrapProperties.addLast(source); } // TODO: is it possible or sensible to share a ResourceLoader? SpringApplicationBuilderbuilder=newSpringApplicationBuilder() .profiles(environment.getActiveProfiles()).bannerMode(Mode.OFF) .environment(bootstrapEnvironment) // Don't use the default properties in this builder .registerShutdownHook(false).logStartupInfo(false) .web(WebApplicationType.NONE); finalSpringApplicationbuilderApplication= 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); finalConfigurableApplicationContextcontext= 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 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; }