html开启时读取配置文件,SpringBoot启动时是如何加载配置文件application.yml文件

spring加载配置文件是通过listener监视器实现的,在springboot启动时:

SpringApplication.java

public ConfigurableApplicationContext run(String... args) {

StopWatch stopWatch = new StopWatch();

stopWatch.start();

ConfigurableApplicationContext context = null;

FailureAnalyzers analyzers = null;

this.configureHeadlessProperty();

SpringApplicationRunListeners listeners = this.getRunListeners(args);

listeners.starting();

try {

ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);

Banner printedBanner = this.printBanner(environment);

context = this.createApplicationContext();

new FailureAnalyzers(context);

this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);

this.refreshContext(context);

this.afterRefresh(context, applicationArguments);

listeners.finished(context, (Throwable)null);

stopWatch.stop();

if (this.logStartupInfo) {

(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);

}

return context;

} catch (Throwable var9) {

this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);

throw new IllegalStateException(var9);

}

}

SpringApplicationRnListeners.java

public void finished(ConfigurableApplicationContext context, Throwable exception) {

Iterator var3 = this.listeners.iterator();

while(var3.hasNext()) {

SpringApplicationRunListener listener = (SpringApplicationRunListener)var3.next();

this.callFinishedListener(listener, context, exception);

}

}

private void callFinishedListener(SpringApplicationRunListener listener, ConfigurableApplicationContext context, Throwable exception) {

try {

listener.finished(context, exception);

} catch (Throwable var6) {

if (exception == null) {

ReflectionUtils.rethrowRuntimeException(var6);

}

if (this.log.isDebugEnabled()) {

this.log.error("Error handling failed", var6);

} else {

String message = var6.getMessage();

message = message == null ? "no error message" : message;

this.log.warn("Error handling failed (" + message + ")");

}

}

}

EventPublishingRunListener.java

public void finished(ConfigurableApplicationContext context, Throwable exception) {

SpringApplicationEvent event = this.getFinishedEvent(context, exception);

if (context != null && context.isActive()) {

context.publishEvent(event);

} else {

if (context instanceof AbstractApplicationContext) {

Iterator var4 = ((AbstractApplicationContext)context).getApplicationListeners().iterator();

while(var4.hasNext()) {

ApplicationListener> listener = (ApplicationListener)var4.next();

this.initialMulticaster.addApplicationListener(listener);

}

}

if (event instanceof ApplicationFailedEvent) {

this.initialMulticaster.setErrorHandler(new EventPublishingRunListener.LoggingErrorHandler());

}

this.initialMulticaster.multicastEvent(event);

}

}

在容器启动完成后会广播一个SpringApplicationEvent事件,而SpringApplicationEvent事件是继承自ApplicationEvent时间的,由于ConfigFileApplicationListener监听器实现了SmartApplicationListener接口,而SmartApplicationListener接口继承了ApplicationListener接口,所以能监听到上面广播出来的SpringApplicationEvent事件

ConfigFileApplicationListener.java

public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {

this.addPropertySources(environment, application.getResourceLoader());

this.configureIgnoreBeanInfo(environment);

this.bindToSpringApplication(environment, application);

}

postProcessEnvironment方法是查找application.yml配置文件的入口方法

protected void addPropertySources(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {

RandomValuePropertySource.addToEnvironment(environment);

(new ConfigFileApplicationListener.Loader(environment, resourceLoader)).load();

}

public void load() {

this.propertiesLoader = new PropertySourcesLoader();

this.activatedProfiles = false;

this.profiles = Collections.asLifoQueue(new LinkedList());

this.processedProfiles = new LinkedList();

Set initialActiveProfiles = this.initializeActiveProfiles();

this.profiles.addAll(this.getUnprocessedActiveProfiles(initialActiveProfiles));

if (this.profiles.isEmpty()) {

String[] var2 = this.environment.getDefaultProfiles();

int var3 = var2.length;

for(int var4 = 0; var4 < var3; ++var4) {

String defaultProfileName = var2[var4];

ConfigFileApplicationListener.Profile defaultProfile = new ConfigFileApplicationListener.Profile(defaultProfileName, true);

if (!this.profiles.contains(defaultProfile)) {

this.profiles.add(defaultProfile);

}

}

}

this.profiles.add((Object)null);

ConfigFileApplicationListener.Profile profile;

label41:

for(; !this.profiles.isEmpty(); this.processedProfiles.add(profile)) {

profile = (ConfigFileApplicationListener.Profile)this.profiles.poll();

Iterator var8 = this.getSearchLocations().iterator();

while(true) {

while(true) {

if (!var8.hasNext()) {

continue label41;

}

String location = (String)var8.next();

if (!location.endsWith("/")) {

this.load(location, (String)null, profile);

} else {

Iterator var10 = this.getSearchNames().iterator();

while(var10.hasNext()) {

String name = (String)var10.next();

this.load(location, name, profile);

}

}

}

}

}

this.addConfigurationProperties(this.propertiesLoader.getPropertySources());

}

默认先读取的是location,然后是配置文件的名字“application”,最后才是文件类型“properties”或者“yml”;

localtion有多种,可以自行debug:有file:./和file:./config和classpath等目录;

文件类型默认的有四种:properties、xml、yml、yaml;

最后查找的具体路径:location + name + "-" + profile + "." + ext;

private void load(String location, String name, ConfigFileApplicationListener.Profile profile) {

String group = "profile=" + (profile == null ? "" : profile);

String ext;

if (!StringUtils.hasText(name)) {

this.loadIntoGroup(group, location, profile);

} else {

for(Iterator var5 = this.propertiesLoader.getAllFileExtensions().iterator(); var5.hasNext(); this.loadIntoGroup(group, location + name + "." + ext, profile)) {

ext = (String)var5.next();

if (profile != null) {

this.loadIntoGroup(group, location + name + "-" + profile + "." + ext, (ConfigFileApplicationListener.Profile)null);

Iterator var7 = this.processedProfiles.iterator();

while(var7.hasNext()) {

ConfigFileApplicationListener.Profile processedProfile = (ConfigFileApplicationListener.Profile)var7.next();

if (processedProfile != null) {

this.loadIntoGroup(group, location + name + "-" + processedProfile + "." + ext, profile);

}

}

this.loadIntoGroup(group, location + name + "-" + profile + "." + ext, profile);

}

}

}

}

根据拼出来的路径去查找配置文件,一般配置文件都放在classpath目录下面,当读取到classpath目录下的配置文件的时候,程序去加载配置文件

private PropertySource> loadIntoGroup(String identifier, String location, ConfigFileApplicationListener.Profile profile) {

try {

return this.doLoadIntoGroup(identifier, location, profile);

} catch (Exception var5) {

throw new IllegalStateException("Failed to load property source from location '" + location + "'", var5);

}

}

private PropertySource> doLoadIntoGroup(String identifier, String location, ConfigFileApplicationListener.Profile profile) throws IOException {

Resource resource = this.resourceLoader.getResource(location);

PropertySource> propertySource = null;

StringBuilder msg = new StringBuilder();

if (resource != null && resource.exists()) {

String name = "applicationConfig: [" + location + "]";

String group = "applicationConfig: [" + identifier + "]";

propertySource = this.propertiesLoader.load(resource, group, name, profile == null ? null : profile.getName());

if (propertySource != null) {

msg.append("Loaded ");

this.handleProfileProperties(propertySource);

} else {

msg.append("Skipped (empty) ");

}

} else {

msg.append("Skipped ");

}

msg.append("config file ");

msg.append(this.getResourceDescription(location, resource));

if (profile != null) {

msg.append(" for profile ").append(profile);

}

if (resource != null && resource.exists()) {

this.logger.debug(msg);

} else {

msg.append(" resource not found");

this.logger.trace(msg);

}

return propertySource;

}

当加载配置文件时,程序先会读取配置文件的spring.profiles.active属性,确定加载什么环境的配置文件(我是加载dev的),然后将读取到的配置文件的属性加载到profiles队列中重新加载配置文件,所以任何项目都必须现有一个基础的配置文件,如application.yml

private void handleProfileProperties(PropertySource> propertySource) {

ConfigFileApplicationListener.SpringProfiles springProfiles = this.bindSpringProfiles(propertySource);

this.maybeActivateProfiles(springProfiles.getActiveProfiles());

this.addProfiles(springProfiles.getIncludeProfiles());

}

private ConfigFileApplicationListener.SpringProfiles bindSpringProfiles(PropertySource> propertySource) {

MutablePropertySources propertySources = new MutablePropertySources();

propertySources.addFirst(propertySource);

return this.bindSpringProfiles((PropertySources)propertySources);

}

private ConfigFileApplicationListener.SpringProfiles bindSpringProfiles(PropertySources propertySources) {

ConfigFileApplicationListener.SpringProfiles springProfiles = new ConfigFileApplicationListener.SpringProfiles();

RelaxedDataBinder dataBinder = new RelaxedDataBinder(springProfiles, "spring.profiles");

dataBinder.bind(new PropertySourcesPropertyValues(propertySources, false));

springProfiles.setActive(this.resolvePlaceholders(springProfiles.getActive()));

springProfiles.setInclude(this.resolvePlaceholders(springProfiles.getInclude()));

return springProfiles;

}

然后在这个配置文件里面有一个active属性,程序会先拿到这个属性,放到profiles属性中,重新去加载配置文件如application-dev.yml

private void addProfiles(Set profiles) {

Iterator var2 = profiles.iterator();

while(var2.hasNext()) {

ConfigFileApplicationListener.Profile profile = (ConfigFileApplicationListener.Profile)var2.next();

this.profiles.add(profile);

if (!this.environmentHasActiveProfile(profile.getName())) {

this.prependProfile(this.environment, profile);

}

}

}

转载至链接:https://my.oschina.net/jzgycq/blog/1934692

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值