溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring Boot自定義配置屬性源(PropertySource)

發(fā)布時間:2020-10-23 10:37:28 來源:腳本之家 閱讀:410 作者:曹書豪 欄目:編程語言

配置覆蓋優(yōu)于profile

在生產實踐中,配置覆蓋是解決不同環(huán)境不同配置的常用方法。比如用生產服務器上的配置文件覆蓋包內的文件,或者使用中心化的配置服務來覆蓋默認的業(yè)務配置。

相比于profile機制(比如maven的profile、spring boot的profile-specific properties),即不同環(huán)境使用不同的配置文件,覆蓋的方式更有優(yōu)勢。程序員在開發(fā)時不需要關心生產環(huán)境數據庫的地址、賬號等信息,一次構建即可在不同環(huán)境中運行,而profile機制需要將生產環(huán)境的配置寫到項目資源文件中,而且要為不同環(huán)境使用不同的構建參數或者運行參數。

Spring提供了靈活的配置擴展能力,有多種方式將自定義的屬性源,將集成進來,可以輕松地實現配置覆蓋。

本文基于Spring Boot 1.4.8/Spring 4.3.12編寫

使用@PropertySource注解實現自定義配置文件和配置覆蓋

@ConfigurationProperties
@Configuration
public class DemoProperties {
  // properties with getter/setters
}
@PropertySource(value = {
    "test.properties",
    "file:/etc/test.properties",
},
    ignoreResourceNotFound = true)
@Configuration
public class DemoAutoConfiguration {

  @Autowired
  private DemoProperties demoProperties;

  @PostConstruct
  public void init() {
    System.out.println(demoProperties);
  }
}

Spring支持使用PropertySource注解引入自定義配置文件,其中"test.properties"將使Spring從classpath下加載該文件,"file:/etc/test.properties"將使Spring從文件系統(tǒng)加載/etc/test.properties文件,ignoreResourceNotFound = true使Spring忽略文件加載失敗的異常,即配置文件是可選的。

同時,由于"file:/etc/test.properties"位于"test.properties"之后,這使得文件系統(tǒng)的配置文件可以覆蓋classpath下的配置。

自定義屬性源工廠

如果想要更加靈活的自定義屬性源,比如實現從中心化的配置服務加載配置,可以通過實現PropertySourceFactory接口,并通過配置PropertySource注解的factory參數來實現。

@Configuration
@PropertySource(value = ""/*placeholder*/,
    factory = CompositePropertySourceFactory.class)
public class CompositeConfigAutoConfiguration {
}

value字段用于指定配置源對應的資源文件,如果不需要使用資源文件,可以配置為任意值,參數值將會被傳遞到factory參數的createPropertySource方法。

如果ignoreResourceNotFound字段指定為true,那么factory拋出的異常將被忽略,否則將導致啟動失敗。有的時候,直接把啟動失敗暴露出來不失為一種好的做法。

PropertySourceFactory接口的定義如下:

/**
 * Strategy interface for creating resource-based {@link PropertySource} wrappers.
 *
 * @author Juergen Hoeller
 * @since 4.3
 * @see DefaultPropertySourceFactory
 */
public interface PropertySourceFactory {

 /**
 * Create a {@link PropertySource} that wraps the given resource.
 * @param name the name of the property source
 * @param resource the resource (potentially encoded) to wrap
 * @return the new {@link PropertySource} (never {@code null})
 * @throws IOException if resource resolution failed
 */
 PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException;

}

需要注意的是PropertySourceFactory的加載時機早于Spring Beans容器,因此實現上不能依賴于Spring的IOC。

PropertySourceFactory要求實現類返回PropertySource。PropertySource是Spring屬性(或者說配置)功能的核心接口,有很多實現,比如:

  1. ResourcePropertySource 從Resource加載PropertySource
  2. PropertiesPropertySource 從properties文件加載PropertySource
  3. SystemEnvironmentPropertySource 從系統(tǒng)環(huán)境變量加載PropertySource
  4. MapPropertySource 包裝一個Map為PropertySource(Adapter模塊)
  5. CompositePropertySource 支持將若干PropertySource進行組合(Composite模式)

實際實現類遠不如這些,具體的可以閱讀Spring文檔或源碼。

在自定義屬性源時比較常用的是MapPropertySource和CompositePropertySource。

MapPropertySource可以用于將自己加載的屬性數據包裝,參考其構造方法。

public MapPropertySource(String name, Map<String, Object> source) {
 super(name, source);
}

后者可以通過組合裝載多個屬性源并自定義覆蓋順序。例如:

PropertySource<?> packageInsidePropertySource = packageInsidePropertySourceIterateLoader.loadPropertySource(compositePropertySource);
compositePropertySource.addPropertySource(packageInsidePropertySource);

PropertySource<?> outerFilePropertySource = outerFilePropertySourceIterateLoader.loadPropertySource(compositePropertySource);
// 優(yōu)先級高于前者
compositePropertySource.addFirstPropertySource(outerFilePropertySource);

addFirstPropertySource方法可以設置傳入的PropertySource為最高優(yōu)先級(在此CompositePropertySource內部),addPropertySource方法則相反,放在后面的優(yōu)先級更低。

加載依賴jar包中所有同名配置文件

直接從classpath加載配置文件,要求文件必須存在于classpath中??紤]在WEB項目中,如果文件存在于某個依賴的jar包中,即位于WEB-INF/lib/xxx.jar中,此時基于classpath無法直接加載。此時可以使用Spring提供的PathMatchingResourcePatternResolver,按資源名稱掃描所有jar包來實現目的。

private List<Resource> getPackageInsideResourcesByPattern(String resourceName) throws IOException {
 String resourcePathPattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + HbootConfigConstants.CONFIGS + resourceName;
 ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
 return Arrays.asList(resourcePatternResolver.getResources(resourcePathPattern));
}

然后就可以使用ResourcePropertySource從Resource構建PropertySource傳給Spring。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI