javascript
Springboot默认加载application.yml原理
Springboot默認加載application.yml原理以及擴展
SpringApplication.run(…)默認會加載classpath下的application.yml或application.properties配置文件。公司要求搭建的框架默認加載一套默認的配置文件demo.properties,讓開發人員實現“零”配置開發,但是前提如果開發人員在application.yml或application.properties文件中自定義配置,則會“覆蓋”默認的demo.properties文件,按照Springboot外部化配置的特性(優先使用先加載的),只要demo.properties配置在application.yml或application.properties 配置之后加載到environment中即可。
一、SpirngApplication.run(…)源碼分析
通過源碼分析,得知Springboot加載配置文件,是利用Spring的事件機制,通過EventPublishingRunListener取發布準備資源事件ApplicationEnvironmentPreparedEvent,被ConfigFileApplicationListener監聽到,從而來實現資源的加載
具體源碼如下:
public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();configureHeadlessProperty();//這里是擴展的關鍵點SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//這里是加載資源的關鍵ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);....} //從方法名稱來看就是準備environment的即配置信息 private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {// Create and configure the environmentConfigurableEnvironment environment = getOrCreateEnvironment();configureEnvironment(environment, applicationArguments.getSourceArgs());//這里默認EventPublishingRunListener發布ApplicationEnvironmentPreparedEvent事件//讓監聽器ConfigFileApplicationListener加載配置文件//這個listeners就是我們擴展的地方listeners.environmentPrepared(environment);bindToSpringApplication(environment);if (this.webApplicationType == WebApplicationType.NONE) {environment = new EnvironmentConverter(getClassLoader()).convertToStandardEnvironmentIfNecessary(environment);}ConfigurationPropertySources.attach(environment);return environment;} SpirngApplication.run(...)方法中有個重要的擴展點方法getRunListeners(args);private SpringApplicationRunListeners getRunListeners(String[] args) {Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));}//可擴展的關鍵點SpringFactoriesLoader//SpringFactoriesLoader會去加載META-INF/spring.factories文件,并根據//type過濾出符合要求的類//比如這里的type對應的是:SpringApplicationRunListenerprivate <T> Collection<T> getSpringFactoriesInstances(Class<T> type,Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = Thread.currentThread().getContextClassLoader();// Use names and ensure unique to protect against duplicatesSet<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));List<T> instances = createSpringFactoriesInstances(type, parameterTypes,classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances;}Springboot默認提供的META-INF/spring.factories,這里就是我們可以擴展的地方
Run Listeners
org.springframework.boot.SpringApplicationRunListener=\ org.springframework.boot.context.event.EventPublishingRunListener至此資源加載的大概流程就分析完了,下面是我們的擴展
二、擴展——自定義加載配置文件(demo.properties)
通過上述源碼分析得知:只需要在項目中添加META-INF/spring.factories,并配置SpringApplicationRunListener為我們自定義的來即可
1、在項目中的resources下創建META-INF/spring.factories
org.springframework.boot.SpringApplicationRunListener=\ com.demo.module.ApplicatonEnvironDemoListener2、ApplicatonEnvironDemoListener的代碼
package com.chyjr.hyboot.demo.module;import org.springframework.boot.SpringApplication;import org.springframework.boot.SpringApplicationRunListener;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.core.PriorityOrdered;import org.springframework.core.env.ConfigurableEnvironment;import org.springframework.core.env.MutablePropertySources;import org.springframework.core.env.PropertiesPropertySource;import org.springframework.core.env.PropertySource;import java.io.IOException;import java.util.Properties;public class ApplicatonEnvironDemoListener implements SpringApplicationRunListener,PriorityOrdered {private SpringApplication application;private String[] args;/*** 通過反射創建該實例對象的,構造方法中的參數要加上如下參數*/public ApplicatonEnvironDemoListener(SpringApplication application,String[] args){this.application = application;this.args = args;}/*** 在準備環境之間調用* SpringApplication#run -> listeners.starting();*/@Overridepublic void starting() {System.out.println("starting-----");}@Overridepublic void environmentPrepared(ConfigurableEnvironment environment) {Properties properties = new Properties();try {//demo.properties就是我們自定義的配置文件,extension是自定義目錄properties.load(this.getClass().getClassLoader().getResourceAsStream("extension/demo.properties"));PropertySource propertySource =new PropertiesPropertySource("demo",properties);//PropertySource是資源加載的核心MutablePropertySources propertySources = environment.getPropertySources();//這里添加最后propertySources.addLast(propertySource);} catch (IOException e) {e.printStackTrace();}}//省略其他方法.../*** 這里可以設置該配置文件加載的順序,在application.yml之前還是之后* EventPublishingRunListener#getOrder方法返回 “0”,按照需求這里我們這是比0大,* 即在application.yml之后加載,這樣在application.yml配置時,可以“覆蓋”my.yml* 這里用“覆蓋”可能不合適,意思到了就好*/@Overridepublic int getOrder() {return 1;}}總結
以上是生活随笔為你收集整理的Springboot默认加载application.yml原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql绿色版安装
- 下一篇: Ubuntu18.04安装TIM、微信