spring 和 spring boot 中的屬性配置方式
本文我們介紹如何在spring中配置和應(yīng)用屬性——通過xml的 或java Configuration 的@PropertySource。
在Spring 3.1之前,將新的屬性文件添加到Spring中及使用屬性值并不是那么靈活和健壯。從Spring 3.1開始,新的Environment 和 PropertySource 抽象已經(jīng)簡化整個(gè)過程。
在xml中注冊屬性文件
通過在xml增加
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<context:property-placeholder location="classpath:foo.properties" />
</beans>
foo.properties文件可以放在/src/main/resources文件夾中,即運(yùn)行時(shí)類路徑。
多個(gè)
如果在Spring上下文中出現(xiàn)了多個(gè) 元素,那么應(yīng)該遵循以下幾個(gè)最佳實(shí)踐:
- 需指定order屬性來確定spring處理順序
- 需要引用其他原始屬性元素應(yīng)該增加ignore-unresolvable= “true”,使解析機(jī)制先不拋出異常的情況下繼續(xù)加載其他配置。
通過java注解方式注冊屬性文件
Spring 3.1 引入新的 @PropertySource 注解,可以方便地給spring environment中添加property source。該注解與基于Java Configuration 方式配置的@Configuration注解一起使用:
@Configuration
@PropertySource("classpath:foo.properties")
public class PropertiesWithJavaConfig {
//...
}
另一個(gè)非常有用的注冊方式為使用占位符方式實(shí)現(xiàn)運(yùn)行時(shí)動態(tài)選擇屬性文件,示例如下:
@PropertySource({
"classpath:persistence-${envTarget:mysql}.properties"
})
…
使用及注入屬性
直接通過 @Value 注解注入屬性:
@Value( "${jdbc.url}" )
private String jdbcUrl;
也可以指定缺省值:
@Value( "${jdbc.url:aDefaultUrl}" )
private String jdbcUrl;
在 Spring XML configuration使用屬性:
<bean id="dataSource">
<property name="url" value="${jdbc.url}" />
</bean>
舊的 PropertyPlaceholderConfigurer 和新的 PropertySourcesPlaceholderConfigurer(Spring 3.1 中引入)都可以解析xml bean定義和@value注解中的 ${…} 占位符 。
最后,使用新的Environment API可以獲取屬性值:
@Autowired
private Environment env;
...
dataSource.setUrl(env.getProperty("jdbc.url"));
特別需要注意的是,使用不會暴露屬性給 Spring Environment,這意味這下面代碼會返回null:
env.getProperty("key.something")
屬性搜索優(yōu)先級
spring4中,默認(rèn)local properties文件最后加載,environment Properties和system Properties之后。local properties是通過PropertiesLoaderSupport 類的API方法 (setProperties, setLocation, etc)手工或編程方式配置的。
這種機(jī)制可以通過設(shè)置PropertySourcesPlaceholderConfigurer類的localOverride 屬性進(jìn)行修改,值為true允許local properties覆蓋spring系統(tǒng)加載的。
spring3.0之前,PropertyPlaceholderConfigurer 類嘗試在手工定義源和System Properties兩個(gè)地方查找,查找順序也可以通過設(shè)置systemPropertiesMode屬性進(jìn)行配置:
- never – 總不檢查 system properties
- fallback (default) – 如果指定的properties files查找不到,則檢查 system properties
- override – 先檢查system properties,然后再嘗試指定的properties files。這允許system properties覆蓋任何其他屬性源。
最后需注意,如果在兩個(gè)或多個(gè)通過@PropertySource定義了屬性,那么最后一個(gè)定義優(yōu)先級最高并覆蓋以前的定義。這使得準(zhǔn)確的屬性值難以預(yù)測,所以如果覆蓋不滿足需求,那么可以重寫PropertySource API。
spring boot 屬性加載
在我們進(jìn)入更高級的屬性配置之前,讓我們先看看Spring Boot中屬性加載的新特性。
總的來說與標(biāo)準(zhǔn)Spring相比,這種新支持的配置更少,當(dāng)然這是Spring Boot的主要目標(biāo)之一。
application.properties – 缺省屬性文件
spring boot 應(yīng)用是典型基于配置文件規(guī)范約定。我們可以簡單地放“application.properties” 文件在“src/main/resources”目錄中,spring boot會自定監(jiān)測,我們能在其中放入任何屬性。
通過使用缺省文件,我們無須顯示注冊PropertySource并指定屬性文件路徑。我們也可以在運(yùn)行時(shí)使用環(huán)境變量屬性指定不同的屬性配置文件:
java -jar app.jar --spring.config.location=classpath:/another-location.properties
特定環(huán)境屬性文件
如果我們需要針對不同環(huán)境,spring boot內(nèi)置機(jī)制可以滿足。我們可以在“src/main/resources”目錄中定義“application-environment.properties” 文件,然后設(shè)置spring profile與environment名稱一致。
例如,如果我們定義“staging” 環(huán)境變量,則我們必須定義staging profile,然后定義application-staging.properties屬性文件。
特定環(huán)境屬性文件加載優(yōu)先級高于缺省屬性文件。注意,默認(rèn)文件仍然會被加載,只是當(dāng)有屬性沖突時(shí),特定環(huán)境屬性文件優(yōu)先。
特定測試屬性文件
在應(yīng)用測試階段,我們可能需要不同的屬性值。Spring Boot通過在測試運(yùn)行期間查找“src/test/resources”目錄中的屬性文件來處理這個(gè)問題。同樣,默認(rèn)屬性仍然會被加載,但是如果發(fā)生沖突,將會覆蓋這些屬性。
@TestPropertySource注解
如果需要更細(xì)粒度控制測試屬性,我們可以使用@TestPropertySource注解。其可以設(shè)置給測試上下文設(shè)置測試屬性,比缺省屬性源優(yōu)先級高:
@ContextConfiguration
@TestPropertySource("/my-test.properties")
public class IntegrationTests {
// tests
}
如果我們不想使用文件,也直接指定名稱和值:
@ContextConfiguration
@TestPropertySource("foo=bar", "bar=foo")
public class IntegrationTests {
// tests
}
也可以通過@SpringBootTest注解,指定相應(yīng)properties參數(shù)值達(dá)到同樣效果:
@SpringBootTest(properties = {"foo=bar", "bar=foo"})
public class IntegrationTests {
// tests
}
層次屬性
如果屬性按分組形式配置,可以使用 @ConfigurationProperties注解,其會按照對象圖方式映射這些分層組織屬性。下面示例看看數(shù)據(jù)庫連接配置屬性:
database.url=jdbc:postgresql:/localhost:5432/instance database.username=foo database.password=bar
然后使用注解映射至數(shù)據(jù)庫對象:
@ConfigurationProperties(prefix = "database")
public class Database {
String url;
String username;
String password;
// standard getters and setters
}
spring boot 在配置方法中再次應(yīng)用了基于約定原則,自動映射屬性值對象字段,我們僅需提供屬性前綴即可。
YAML 文件
YAML文件也支持。
同樣名稱規(guī)則可以應(yīng)用至測試規(guī)范、environmet規(guī)范以及缺省屬性文件。僅文件擴(kuò)展名不同以及需提供SnakeYAML依賴。
YAML對層次屬性存儲特別方便,下面的屬性文件:
database.url=jdbc:postgresql:/localhost:5432/instance database.username=foo database.password=bar secret: foo
對應(yīng)的YAML文件為:
database: url: jdbc:postgresql:/localhost:5432/instance username: foo password: bar secret: foo
需要注意的是YAML文件不支持使用@PropertySource注解,所以如果使用該注解則必須使用屬性文件。
命令行傳入屬性
相對于使用文件,屬性也可以直接通過命令行進(jìn)行傳遞:
java -jar app.jar --property="value"
你也能通過系統(tǒng)屬性實(shí)現(xiàn),需要在-jar命令之前提供:
java -Dproperty.name="value" -jar app.jar
環(huán)境變量屬性
spring boot也能監(jiān)測環(huán)境變量,效果與屬性一樣:
export name=value java -jar app.jar
隨機(jī)屬性值
如果屬性值不確定,RandomValuePropertySource 可以實(shí)現(xiàn)給屬性賦隨機(jī)值:
random.number=${random.int}
random.long=${random.long}
random.uuid=${random.uuid}
其他類型的屬性源
spring boot 支持很多屬性源,實(shí)現(xiàn)較好順序及合理覆蓋。其官方文檔可以參閱。
spring配置實(shí)現(xiàn)
- spring3.1之前
spring3.1引入注解,可以方便地定義屬性源,在此之前,xml配置是必須的。 xml元素自動在spring上下文中注冊新的PropertyPlaceholderConfigurer bean。為了向后兼容,在spring3.1及之后版本中,如果XSD schemas不升級到新的3.1 XSD版本,仍然會創(chuàng)建相應(yīng)bean。
- spring3.1之后
從spring3.1起,XML 元素不再注冊舊的PropertyPlaceholderConfigurer 類,代替引入PropertySourcesPlaceholderConfigurer類,新的類可以實(shí)現(xiàn)更靈活地和Environment 和 PropertySource機(jī)制進(jìn)行交互。
對3.1之后版本,應(yīng)該應(yīng)用新的標(biāo)準(zhǔn)。
多層級上下文中屬性加載
當(dāng)web應(yīng)用有父和子上下文時(shí),屬性如何加載是很常見的問題。父上下文有一些通用的核心功能和bean,并包括一個(gè)或多個(gè)子上下文,可能包含servlet特定的bean。
這種場景下,如何最佳方式定義屬性文件并引入到各自的上下文中?以及如何在spring中以最佳方式獲取這些屬性,下面分類進(jìn)行說明:
屬性文件通過定義xml中
如果文件定義在父上下文:
- @Value 在子上下文 : 否
- @Value 在父上下文 : 是
如果文件定義在子上下文:
- @Value 在子上下文 : 是
- @Value 在父上下文 : 否
總之如上所述,沒有暴露屬性給environment,所以environment.getProperty在上下文中不工作。
屬性文件通過@PropertySource定義在java中
如果文件定義在父上下文:
- @Value 在子上下文 : 是
- @Value 在父上下文 : 是
- environment.getProperty 在子上下文: 是
- environment.getProperty 在父上下文: 是
如果文件定義在子上下文:
- @Value 在子上下文 : 是
- @Value 在父上下文 : 否
- environment.getProperty 在子上下文: 是
- environment.getProperty 在父上下文: 否
總結(jié)
本文通過幾個(gè)示例說明了spring中加載屬性機(jī)制。希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java如何實(shí)現(xiàn)獲取客戶端ip地址的示例代碼
本文主要介紹了java如何實(shí)現(xiàn)獲取客戶端ip地址,主要包括java獲取客戶端ip地址工具類使用實(shí)例、應(yīng)用技巧,文中通過示例代碼介紹的非常詳細(xì),感興趣的小伙伴們可以參考一下2022-04-04
windows系統(tǒng)配置Java開發(fā)環(huán)境變量
這篇文章主要介紹了windows系統(tǒng)配置Java開發(fā)環(huán)境變量,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2021-12-12
Android中Socket通信的實(shí)現(xiàn)方法概述
這篇文章主要介紹了Android中Socket通信的實(shí)現(xiàn)方法,很有實(shí)用價(jià)值,需要的朋友可以參考下2014-08-08
mall整合SpringSecurity及JWT認(rèn)證授權(quán)實(shí)戰(zhàn)下
這篇文章主要為大家介紹了mall整合SpringSecurity及JWT認(rèn)證授權(quán)實(shí)戰(zhàn)第二篇,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
Mybatis-Plus實(shí)現(xiàn)公共字段自動賦值的方法
這篇文章主要介紹了Mybatis-Plus實(shí)現(xiàn)公共字段自動賦值的方法,涉及到通用字段自動填充的最佳實(shí)踐總結(jié),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07
Spring?Boot?打包成Jar包運(yùn)行原理分析
這篇文章主要為大家介紹了Spring?Boot?打包成Jar包運(yùn)行的原理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
SpringBoot整合Canal與RabbitMQ監(jiān)聽數(shù)據(jù)變更記錄
這篇文章主要介紹了SpringBoot整合Canal與RabbitMQ監(jiān)聽數(shù)據(jù)變更記錄,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09
Mybatis plus 配置多數(shù)據(jù)源的實(shí)現(xiàn)示例
這篇文章主要介紹了Mybatis plus 配置多數(shù)據(jù)源的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08

