最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Boot加載配置文件的完整步驟

 更新時(shí)間:2019年11月05日 08:31:23   作者:架構(gòu)文摘  
這篇文章主要給大家介紹了關(guān)于Spring Boot加載配置文件的完整步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

本文針對版本2.2.0.RELEASE來分析SpringBoot的配置處理源碼,通過查看SpringBoot的源碼來弄清楚一些常見的問題比如:

  1. SpringBoot從哪里開始加載配置文件?
  2. SpringBoot從哪些地方加載配置文件?
  3. SpringBoot是如何支持yaml和properties類型的配置文件?
  4. 如果要支持json配置應(yīng)該如何做?
  5. SpringBoot的配置優(yōu)先級是怎么樣的?
  6. placeholder是如何被解析的?

帶著我們的問題一起去看一下SpringBoot配置相關(guān)的源代碼,找出問題的答案。

SpringBoot從哪里開始加載配置文件?

SpringBoot加載配置文件的入口是由ApplicationEnvironmentPreparedEvent事件進(jìn)入的,SpringBoot會(huì)在SpringApplication的構(gòu)造函數(shù)中通過spring.factories文件獲取ApplicationListener的實(shí)例類:

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
 ...
 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
 ...
}

spring.factories中有一個(gè)ConfigFileApplicationListener類,它會(huì)監(jiān)聽ApplicationEnvironmentPreparedEvent然后再加載配置文件 :

# Application Listeners
org.springframework.context.ApplicationListener= org.springframework.boot.context.config.ConfigFileApplicationListener
...

有了事件和事件處理的類后,再找出發(fā)送事件的地方,就可以搞清楚SpringBoot是怎么加載配置文件的了,SpringBoot在啟動(dòng)之前先初始化好SpringApplicationRunListeners這個(gè)類,它會(huì)實(shí)現(xiàn)SpringApplicationRunListener接口然后對事件進(jìn)行轉(zhuǎn)發(fā):

class SpringApplicationRunListeners {

 private final Log log;

 private final List<SpringApplicationRunListener> listeners;

 SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
 this.log = log;
 this.listeners = new ArrayList<>(listeners);
 }
 
 void environmentPrepared(ConfigurableEnvironment environment) {
 for (SpringApplicationRunListener listener : this.listeners) {
 listener.environmentPrepared(environment);
 }
 }
 ...
}

獲取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 Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

小結(jié)

  • SpringBoot會(huì)將事件轉(zhuǎn)換成ApplicationEvent再分發(fā)
  • SpringBoot是通過監(jiān)聽ApplicationEnvironmentPreparedEvent事件來加載配置文件的
  • 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";

首先在沒有任何配置的情況下,會(huì)從DEFAULT_SEARCH_LOCATIONS常量列出來的位置中加載文件名為DEFAULT_NAMES(.properties或yml)的文件,默認(rèn)位置包括:

  • classpath根目錄(classpath:/)
  • classpath里面的config文件目錄(classpath:/config/)
  • 程序運(yùn)行目錄(file:./)
  • 程序運(yùn)行目錄下的config目錄(file:./config/)

上面說的是沒有額外配置的情況,SpringBoot足夠靈活可以指定配置文件搜索路徑、配置文件名,在ConfigFileApplicationListener類中有個(gè)getSearchLocations方法,它主要負(fù)責(zé)獲取配置搜索目錄:

private Set<String> getSearchLocations() {
if (this.environment.containsProperty(CONFIG_LOCATION_PROPERTY)) {
 return getSearchLocations(CONFIG_LOCATION_PROPERTY);
 }
 Set<String> locations = getSearchLocations(CONFIG_ADDITIONAL_LOCATION_PROPERTY);
 locations.addAll(
 asResolvedSet(ConfigFileApplicationListener.this.searchLocations, DEFAULT_SEARCH_LOCATIONS));
 return locations;
}

它的操作步驟大致如下:

  1. 檢查是否有spring.config.location屬性,如果存在則直接使用它的值
  2. 從spring.config.additional-location屬性中獲取搜索路徑
  3. 將默認(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對象的時(shí)候就會(huì)先加載PropertySourceLoader,加載方式還是從spring.factories中讀取:

# PropertySource Loaders
org.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<PropertySource<?>> load(String name, Resource resource) throws IOException {

 if(resource == null || !resource.exists()){
  return Collections.emptyList();
 }

 Map<String, Object> configs = JSON.parseObject(resource.getInputStream(), Map.class);

 return Collections.singletonList(
  new MapPropertySource(name, configs)
 );
 }
}

然后在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)先級是怎么樣的?

SpringBoot中有個(gè)PropertySource接口,專門用來保存屬性常見的實(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)先級越高,所以如果想要覆蓋屬性只要保證優(yōu)化級夠高就行。

placeholder是如何被解析的?

繼續(xù)分析ConfigFileApplicationListener的Loader子類,在構(gòu)造時(shí)還會(huì)創(chuàng)建一個(gè)PropertySourcesPlaceholdersResolver,placeholder的解析都由它來完成:

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<PropertySource<?>> sources, PropertyPlaceholderHelper helper) {
 this.sources = sources;
 this.helper = (helper != null) ? helper : new PropertyPlaceholderHelper(SystemPropertyUtils.PLACEHOLDER_PREFIX,
  SystemPropertyUtils.PLACEHOLDER_SUFFIX, SystemPropertyUtils.VALUE_SEPARATOR, true);
}

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í)就能知道以什么格式來解析比如:${spring.application.name}這個(gè)placeholder就會(huì)被解析成屬性值。

總結(jié)

SpringBoot的配置非常靈活配置可以來自文件、環(huán)境變量、JVM系統(tǒng)屬性、配置中心等等,SpringBoot通過
PropertySource和PropertySources實(shí)現(xiàn)屬性優(yōu)先級、CRUD的統(tǒng)一管理,為開發(fā)者提供統(tǒng)一的配置抽象。

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對腳本之家的支持。

相關(guān)文章

  • Mybatis實(shí)現(xiàn)數(shù)據(jù)的增刪改查實(shí)例(CRUD)

    Mybatis實(shí)現(xiàn)數(shù)據(jù)的增刪改查實(shí)例(CRUD)

    本篇文章主要介紹了Mybatis實(shí)現(xiàn)數(shù)據(jù)的增刪改查實(shí)例(CRUD),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • 關(guān)于springboot配置druid數(shù)據(jù)源不生效問題(踩坑記)

    關(guān)于springboot配置druid數(shù)據(jù)源不生效問題(踩坑記)

    今天日常跟著網(wǎng)課學(xué)習(xí),學(xué)到了整合druid數(shù)據(jù)源,遇到了好幾個(gè)坑,希望這篇文章可以幫助一些和我一樣踩坑的人
    2021-09-09
  • Spring?Boot+RabbitMQ?通過fanout模式實(shí)現(xiàn)消息接收功能(支持消費(fèi)者多實(shí)例部署)

    Spring?Boot+RabbitMQ?通過fanout模式實(shí)現(xiàn)消息接收功能(支持消費(fèi)者多實(shí)例部署)

    這篇文章主要介紹了Spring?Boot+RabbitMQ?通過fanout模式實(shí)現(xiàn)消息接收(支持消費(fèi)者多實(shí)例部署),本文通過案例場景分析給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • 淺談java中的TreeMap 排序與TreeSet 排序

    淺談java中的TreeMap 排序與TreeSet 排序

    下面小編就為大家?guī)硪黄獪\談java中的TreeMap 排序與TreeSet 排序。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • Spring?boot?處理大文件上傳完整代碼

    Spring?boot?處理大文件上傳完整代碼

    這篇文章主要介紹了Spring?boot?處理大文件上傳,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • springboot多環(huán)境進(jìn)行動(dòng)態(tài)配置的方法

    springboot多環(huán)境進(jìn)行動(dòng)態(tài)配置的方法

    這篇文章主要介紹了springboot多環(huán)境下如何進(jìn)行動(dòng)態(tài)配置,本文主要分享了如何在springboot的項(xiàng)目中使用多環(huán)境配置,重點(diǎn)是”spring.profiles.active“屬性,需要的朋友可以參考下
    2022-06-06
  • Oracle JDBC連接BUG解決方案

    Oracle JDBC連接BUG解決方案

    這篇文章主要介紹了Oracle JDBC連接BUG解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Java實(shí)現(xiàn)異步執(zhí)行的8種方式總結(jié)

    Java實(shí)現(xiàn)異步執(zhí)行的8種方式總結(jié)

    這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)異步執(zhí)行的8種方式,異步編程不會(huì)阻塞程序的執(zhí)行,它將耗時(shí)的操作提交給后臺(tái)線程或其他執(zhí)行環(huán)境,并立即返回,使得程序可以繼續(xù)執(zhí)行其他任務(wù),需要的朋友可以參考下
    2023-09-09
  • springmvc限流攔截器的示例代碼

    springmvc限流攔截器的示例代碼

    本篇文章主要介紹了springmvc限流攔截器的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • SpringBoot下載文件遇到文件損壞等問題解決方案

    SpringBoot下載文件遇到文件損壞等問題解決方案

    調(diào)用接口下載spring?boot工程的resources目錄下的excel模板文件,非常常見的一個(gè)文件下載功能,但是卻容易遇到很多坑,下面總結(jié)記錄下
    2023-10-10

最新評論

万安县| 永康市| 石狮市| 清新县| 新宾| 泰顺县| 凤山县| 聂荣县| 稷山县| 博客| 游戏| 噶尔县| 海门市| 丰镇市| 承德市| 资中县| 通山县| 朝阳县| 商洛市| 怀化市| 太和县| 临城县| 彭州市| 顺昌县| 彩票| 青州市| 石嘴山市| 澜沧| 商水县| 图木舒克市| 阿荣旗| 涟源市| 班玛县| 开原市| 赣榆县| 抚州市| 建始县| 五华县| 肇州县| 淳安县| 五大连池市|