springboot启动之后,
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.sources = new LinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
this.webApplicationType = this.deduceWebApplicationType();
<-----------------------↓↓↓----------------------->
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
<-----------------------↑↑↑----------------------->
this.mainApplicationClass = this.deduceMainApplicationClass();
}
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
<-----------------------↓↓↓----------------------->
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
<-----------------------↑↑↑----------------------->
this.configureIgnoreBeanInfo(environment);
Banner printedBanner = this.printBanner(environment);
context = this.createApplicationContext();
this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var9) {
this.handleRunFailure(context, listeners, exceptionReporters, var9);
throw new IllegalStateException(var9);
}
listeners.running(context);
return context;
}
接下来会触发environmentPrepared事件,在一些列调用后会发布ApplicationEnvironmentPreparedEvent事件,如下
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
<-----------------------↓↓↓----------------------->
listeners.environmentPrepared((ConfigurableEnvironment)environment);
<-----------------------↑↑↑----------------------->
this.bindToSpringApplication((ConfigurableEnvironment)environment);
if (this.webApplicationType == WebApplicationType.NONE) {
environment = (new EnvironmentConverter(this.getClassLoader())).convertToStandardEnvironmentIfNecessary((ConfigurableEnvironment)environment);
}
ConfigurationPropertySources.attach((Environment)environment);
return (ConfigurableEnvironment)environment;
}
在这里面我们主要关注这个类ConfigFileApplicationListener
接下来我们看这个方法
private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
1. List<EnvironmentPostProcessor> postProcessors = this.loadPostProcessors();
2. postProcessors.add(this);
3. AnnotationAwareOrderComparator.sort(postProcessors);
4. Iterator var3 = postProcessors.iterator();
while(var3.hasNext()) {
EnvironmentPostProcessor postProcessor = (EnvironmentPostProcessor)var3.next();
postProcessor.postProcessEnvironment(event.getEnvironment(), event.getSpringApplication());
}
}
第一行获取
@FunctionalInterface
public interface EnvironmentPostProcessor {
void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application);
}
EnvironmentPostProcessor 的实现方法,从META-INF/spring.factories中获取。
第二行把当前类,也就是ConfigFileApplicationListener这个类,因为这个类也实现了EnvironmentPostProcessor 接口,所以这个类也被加入了进来。
接下来就开始执行EnvironmentPostProcessor
我们只需要关注ConfigFileApplicationListener类中的如下方法。
这一步会完成
public void load() {
this.profiles = Collections.asLifoQueue(new LinkedList());
this.processedProfiles = new LinkedList();
this.activatedProfiles = false;
this.loaded = new LinkedHashMap();
<-----------------------↓↓↓----------------------->
this.initializeProfiles();
<-----------------------↑↑↑----------------------->
while(!this.profiles.isEmpty()) {
ConfigFileApplicationListener.Profile profile = (ConfigFileApplicationListener.Profile)this.profiles.poll();
this.load(profile, this::getPositiveProfileFilter, this.addToLoaded(MutablePropertySources::addLast, false));
this.processedProfiles.add(profile);
}
<-----------------------↓↓↓----------------------->
this.load((ConfigFileApplicationListener.Profile)null, this::getNegativeProfileFilter, this.addToLoaded(MutablePropertySources::addFirst, true));
<-----------------------↑↑↑----------------------->
this.addLoadedPropertySources();
}
public void load() {
this.profiles = Collections.asLifoQueue(new LinkedList());
this.processedProfiles = new LinkedList();
this.activatedProfiles = false;
this.loaded = new LinkedHashMap();
this.initializeProfiles();
while(!this.profiles.isEmpty()) {
ConfigFileApplicationListener.Profile profile = (ConfigFileApplicationListener.Profile)this.profiles.poll();
this.load(profile, this::getPositiveProfileFilter, this.addToLoaded(MutablePropertySources::addLast, false));
this.processedProfiles.add(profile);
}
<-----------------------↓↓↓----------------------->
this.load((ConfigFileApplicationListener.Profile)null, this::getNegativeProfileFilter, this.addToLoaded(MutablePropertySources::addFirst, true));
this.addLoadedPropertySources();
<-----------------------↑↑↑----------------------->
}
扩展:
在遍历配置文件的时候会按照如下规则进行查找
private Set<String> getSearchLocations() {
if (this.environment.containsProperty("spring.config.location")) {
return this.getSearchLocations("spring.config.location");
} else {
Set<String> locations = this.getSearchLocations("spring.config.additional-location");
locations.addAll(this.asResolvedSet(ConfigFileApplicationListener.this.searchLocations, "classpath:/,classpath:/config/,file:./,file:./config/"));
return locations;
}
}
至此本地的环境变量,配置文件已经读取完毕了,不过配置还缺少一步就是当我们用到配置中心的时候还需要执行如下操作,这里我们以apollo为例进行简单的说明。这个时候前面提到的initializers就派上用场了。看代码
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
Banner printedBanner = this.printBanner(environment);
context = this.createApplicationContext();
this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
<-----------------------↓↓↓----------------------->
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
<-----------------------↑↑↑----------------------->
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var9) {
this.handleRunFailure(context, listeners, exceptionReporters, var9);
throw new IllegalStateException(var9);
}
listeners.running(context);
return context;
}
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
this.postProcessApplicationContext(context);
<-----------------------↓↓↓----------------------->
this.applyInitializers(context);
<-----------------------↑↑↑----------------------->
listeners.contextPrepared(context);
if (this.logStartupInfo) {
this.logStartupInfo(context.getParent() == null);
this.logStartupProfileInfo(context);
}
context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
Set<Object> sources = this.getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
this.load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
在this.applyInitializers(context);这里会执行apollo的
从而完成了配置中心的配置,至此所有配置均已完成。
-------------------------------->抛砖引玉