重慶分公司,新征程啟航
為企業(yè)提供網(wǎng)站建設(shè)、域名注冊(cè)、服務(wù)器等服務(wù)
為企業(yè)提供網(wǎng)站建設(shè)、域名注冊(cè)、服務(wù)器等服務(wù)
這篇文章給大家介紹SpringBoot加載配置文件的完整步驟是什么,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
目前創(chuàng)新互聯(lián)已為上千的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)頁(yè)空間、網(wǎng)站托管、服務(wù)器租用、企業(yè)網(wǎng)站設(shè)計(jì)、加格達(dá)奇網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
SpringBoot從哪里開(kāi)始加載配置文件?
SpringBoot加載配置文件的入口是由ApplicationEnvironmentPreparedEvent事件進(jìn)入的,SpringBoot會(huì)在SpringApplication的構(gòu)造函數(shù)中通過(guò)spring.factories文件獲取ApplicationListener的實(shí)例類:
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) { ... setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); ...}
spring.factories中有一個(gè)ConfigFileApplicationListener類,它會(huì)監(jiān)聽(tīng)ApplicationEnvironmentPreparedEvent然后再加載配置文件 :
# Application Listenersorg.springframework.context.ApplicationListener= org.springframework.boot.context.config.ConfigFileApplicationListener...
有了事件和事件處理的類后,再找出發(fā)送事件的地方,就可以搞清楚SpringBoot是怎么加載配置文件的了,SpringBoot在啟動(dòng)之前先初始化好SpringApplicationRunListeners這個(gè)類,它會(huì)實(shí)現(xiàn)SpringApplicationRunListener接口然后對(duì)事件進(jìn)行轉(zhuǎn)發(fā):
class SpringApplicationRunListeners { private final Log log; private final List
獲取SpringApplicationRunListeners的代碼如下:
private SpringApplicationRunListeners getRunListeners(String[] args) { Class>[] types = new Class>[] { SpringApplication.class, String[].class }; return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));}
同樣也會(huì)去加載spring.factories文件,該文件有一個(gè)EventPublishingRunListener類,該類的作用就是SpringBoot的事件轉(zhuǎn)換成ApplicationEvent發(fā)送出去。
# Run Listenersorg.springframework.boot.SpringApplicationRunListener=\org.springframework.boot.context.event.EventPublishingRunListener
小結(jié)
SpringBoot會(huì)將事件轉(zhuǎn)換成ApplicationEvent再分發(fā) SpringBoot是通過(guò)監(jiān)聽(tīng)ApplicationEnvironmentPreparedEvent事件來(lái)加載配置文件的 ConfigFileApplicationListener是處理配置文件的主要類
SpringBoot從哪些地方加載配置文件?
上面已經(jīng)分析到ConfigFileApplicationListener是處理配置文件的主要類,然后進(jìn)一步的查看SpringBoot是從哪些地址加載配置文件,進(jìn)入ConfigFileApplicationListener類后會(huì)有兩個(gè)默認(rèn)的常量:
private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/";private static final String DEFAULT_NAMES = "application";
首先在沒(méi)有任何配置的情況下,會(huì)從DEFAULT_SEARCH_LOCATIONS常量列出來(lái)的位置中加載文件名為DEFAULT_NAMES(.properties或yml)的文件,默認(rèn)位置包括:
classpath根目錄(classpath:/) classpath里面的config文件目錄(classpath:/config/) 程序運(yùn)行目錄(file:./) 程序運(yùn)行目錄下的config目錄(file:./config/)
上面說(shuō)的是沒(méi)有額外配置的情況,SpringBoot足夠靈活可以指定配置文件搜索路徑、配置文件名,在ConfigFileApplicationListener類中有個(gè)getSearchLocations方法,它主要負(fù)責(zé)獲取配置搜索目錄:
private Set
它的操作步驟大致如下:
檢查是否有spring.config.location屬性,如果存在則直接使用它的值 從spring.config.additional-location屬性中獲取搜索路徑 將默認(rèn)搜索路徑添加到搜索集合
這里就可以確定SpringBoot配置的搜索路徑有兩種情況:如果配置了spring.config.location則直接使用,否則使用spring.config.additional-location的屬性值 + 默認(rèn)搜索路徑。
SpringBoot是如何支持yaml和properties類型的配置文件?
SpringBoot的配置支持properties和yaml文件,SpringBoot是如何解析這兩種文件的呢,繼續(xù)分析ConfigFileApplicationListener這個(gè)類,里面有個(gè)子類叫Loader加載配置文件主要的工作就是由這貨負(fù)責(zé),但是直接讀取properties和yaml并轉(zhuǎn)換成PropertySource還是由里面的PropertySourceLoader負(fù)責(zé):
Loader(ConfigurableEnvironment environment, ResourceLoader resourceLoader) { ... this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class, getClass().getClassLoader());}
構(gòu)造Loader對(duì)象的時(shí)候就會(huì)先加載PropertySourceLoader,加載方式還是從spring.factories中讀?。?/p>
# PropertySource Loadersorg.springframework.boot.env.PropertySourceLoader=\org.springframework.boot.env.PropertiesPropertySourceLoader,\org.springframework.boot.env.YamlPropertySourceLoader
其中配置了兩個(gè)PropertySourceLoader的實(shí)現(xiàn)類:
PropertiesPropertySourceLoader YamlPropertySourceLoader
看名字就知道是分別負(fù)責(zé)properties和yaml的啦。
如果要支持json配置應(yīng)該如何做?
如果不喜歡properties和yaml這兩種格式,想要定義json做為配置文字格式可以直接定義json類型的PropertySourceLoader:
public class JSONPropertySourceLoader implements PropertySourceLoader { @Override public String[] getFileExtensions() { return new String[] {"json"}; } @Override public List
然后在resources目錄里面建立個(gè)META-INF,再添加個(gè)spring.factories里面的內(nèi)容如下:
org.springframework.boot.env.PropertySourceLoader=\com.csbaic.arch.spring.env.loader.JSONPropertySourceLoader
最后在resources目錄里面建個(gè)application.json的配置文件 :
{ "spring.application.name": "JSONConfig"}
正常啟動(dòng)SpringBoot獲取spring.applicaiton.name的配置的值就是JSONConfig:
2019-11-02 14:50:17.730 INFO 55275 --- [ main] c.c.a.spring.env.SpringEnvApplication : JSONConfig
SpringBoot的配置優(yōu)先級(jí)是怎么樣的?
SpringBoot中有個(gè)PropertySource接口,專門用來(lái)保存屬性常見(jiàn)的實(shí)現(xiàn)類有:
CommandLinePropertySource MapPropertySource SystemEnvironmentPropertySource ....
另外為了集中管理PropertySource還抽象出一個(gè)PropertySources接口,PropertySources就一個(gè)實(shí)現(xiàn)類叫:MutablePropertySources,它將所有的PropertySource都放置在一個(gè)名叫propertySourceList集合中,同時(shí)提供一些修改操作方法:
public void addFirst(PropertySource> propertySource) {}public void addLast(PropertySource> propertySource) {}public void addBefore(String relativePropertySourceName, PropertySource> propertySource) {}public void addAfter(String relativePropertySourceName, PropertySource> propertySource) {}public int precedenceOf(PropertySource> propertySource) { }public PropertySource> remove(String name) {}public void replace(String name, PropertySource> propertySource) {}
所有的PropertySource都保存在propertySourceList中,越小的索引優(yōu)先級(jí)越高,所以如果想要覆蓋屬性只要保證優(yōu)化級(jí)夠高就行。
placeholder是如何被解析的?
繼續(xù)分析ConfigFileApplicationListener的Loader子類,在構(gòu)造時(shí)還會(huì)創(chuàng)建一個(gè)PropertySourcesPlaceholdersResolver,placeholder的解析都由它來(lái)完成:
Loader(ConfigurableEnvironment environment, ResourceLoader resourceLoader) { this.placeholdersResolver = new PropertySourcesPlaceholdersResolver(this.environment);}
分析PropertySourcesPlaceholdersResolver發(fā)現(xiàn),真正完成解析是由PropertyPlaceholderHelper完成,PropertySourcesPlaceholdersResolver 在構(gòu)造的時(shí)候就會(huì)創(chuàng)建一個(gè)PropertyPlaceholderHelper
public PropertySourcesPlaceholdersResolver(Iterable
PropertySourcesPlaceholdersResolver 在創(chuàng)建 PropertyPlaceholderHelper 的時(shí)候會(huì)傳遞三個(gè)參數(shù):前綴、后綴、默認(rèn)值分割符,分別由以下三個(gè)常量表示:
public static final String PLACEHOLDER_PREFIX = "${";public static final String PLACEHOLDER_SUFFIX = "}";public static final String VALUE_SEPARATOR = ":";
這樣 PropertyPlaceholderHelper 在解析placeholder時(shí)就能知道以什么格式來(lái)解析比如:${spring.application.name}這個(gè)placeholder就會(huì)被解析成屬性值。
總結(jié)
SpringBoot的配置非常靈活配置可以來(lái)自文件、環(huán)境變量、JVM系統(tǒng)屬性、配置中心等等,SpringBoot通過(guò)PropertySource和PropertySources實(shí)現(xiàn)屬性優(yōu)先級(jí)、CRUD的統(tǒng)一管理,為開(kāi)發(fā)者提供統(tǒng)一的配置抽象。
關(guān)于SpringBoot加載配置文件的完整步驟是什么就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。