一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
现在开发主要使用微服务框架springboot,在springboot中经常遇到读取application.yml文件的情形。
使用它的过程代码也比较简单,使用@Value注解既可以完成调用,示例如下:
@Value("${spring.mail.username}")
private String userName;
但是之前从来没有了解过SpringBoot加载配置文件的过程。今天我也来学习下入口加载配置文件。
加载监听器
依旧是通过SpringApplication的启动过程去跟踪,启动时跟踪run方法,可以看到在SpringApplication.class文件中的run方法
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();
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 加载SpringBoot配置环境
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
Banner printedBanner = this.printBanner(environment);
context = this.createApplicationContext();
exceptionReporters = 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 var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
这个过程,应用的监听器SpringApplicationRunListeners并开始监听,通过prepareEnvironment方法准备environment的配置信息,,其中加载配置文件的监听器就在循环列表中,加载SpringBoot配置环境(ConfigurableEnvironment),在prepareEnvironment方法中会执行EventPublishingRunListener中的environmentPrepared()方法,
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
}
initialMulticaster可以找到SimpleApplicationEventMulticaster类中的doInvokeListener()方法,进入到ConfigFiledApplicationListerner类中,执行onApplicationEnviromentPrepareEvent()方法,
重点看ConfigFileApplicationListener类中的postProcessEnvironment方法,其中会添加一个属性源进来ResourceLoader,会调用load方法加载属性,
进入load方法,执行一个初始化方法initializeProfiles,方法中会向profiles中放入null,然后再放入一个"default",用来从外部遍历,遍历为null的时候,加载springboot的默认配置,遍历为“default"时,加载用户配置。
执行getSearchLocations方法,获取默认的路径classpath:/,classpath:/config/,file:./,file:./config/*/,file:./config/
获取配置文件名字,如果配置spring.confing.name的话,则去配置的名字,否则用默认的"application"
最终通过以钩子程序的形式调用函数式编程完成属性的赋值。
好了,本文就给大家介绍到这里,感觉有帮助的,留下个赞或评论再走吧!谢啦~ 💐