https://blog.csdn.net/qq_30739519/article/list/3
注解
https://blog.csdn.net/qq_30739519/article/details/78791142
https://blog.csdn.net/qq_30739519/article/details/78800490
https://blog.csdn.net/qq_30739519/article/details/78779317
Springboot集成Swagger2
摘要:Springboot中PropertySource注解的使用一文中,詳細講解了PropertySource注解的使用,通過PropertySource注解去加載指定的資源文件、然后將加載的屬性注入到指定的配置類,@value以及@ConfigurationProperties的使用。但是也遺留一個問題,PropertySource注解貌似是不支持多種環境的動態切換?這個問題該如何解決呢?我們需要從源碼中看看他到底是否支持。
————————————————
版權聲明:本文為CSDN博主「分享牛」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_30739519/java/article/details/78800490
摘要:本文重點講解一下Spring中@PropertySource注解的使用,如何通過PropertySource注解加載指定的配置文件。以及PropertySource注解與@ConfigurationProperties兩個注解的配合使用。
1.1. PropertySource注解加載指定的屬性文件
Spring框架提供了PropertySource注解,目的是加載指定的屬性文件,接下來我們看一下如何使用該注解。首先我們定義一個配置類,並在類中添加PropertySource注解,如下所示:
@Component
@PropertySource(value= {"classpath:config/jdbc-bainuo-dev.properties"},ignoreResourceNotFound=false,encoding="UTF-8",name="jdbc-bainuo-dev.properties",)
public class CustomerDataSourceConfig1 {
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "CustomerDataSourceConfig{" +
"url='" + url + '\'' +
'}';
}
}
上述的代碼目的是加載classpath路徑中config文件中的jdbc-bainuo-dev.properties。其中encoding
用於指定讀取屬性文件所使用的編碼,我們通常使用的是UTF-8;ignoreResourceNotFound含義是當指定的配置文件不存在是否報錯,默認是false;比如上文中指定的加載屬性文件是jdbc-bainuo-dev.properties。如果該文件不存在,則ignoreResourceNotFound為true的時候,程序不會報錯,如果ignoreResourceNotFound為false的時候,程序直接報錯。實際項目開發中,最好設置ignoreResourceNotFound為false。該參數默認值為false。
value值是設置需要加載的屬性文件,可以一次性加載多個。name的值我們設置的是jdbc-bainuo-dev.properties。這個值在Springboot的環境中必須是唯一的,如果不設置,則值為:“class path resource [config/jdbc-bainuo-dev.properties]“。
可能很多人比較納悶,為什么是“class path resource [config/jdbc-bainuo-dev.properties]“呢?這個就涉及到了Spring中對資源文件的封裝類Resource。上文我們配置的value值為"classpath:config/jdbc-bainuo-dev.properties",因此Spring發現是classpath開頭的,因此最終使用的是Resource的子類ClassPathResource。如果是file開頭的,則最終使用的類是FileSystemResource。
了解了上文所述的Resource類之后。我們再次明確一點,如果@PropertySource中如果沒有設置name值,則name值的生成規則是:根據value值查找到最終封裝的Resource子類,然后調用具體的Resource子類實例對象中的getDescription方法,getDescription方法的返回值為最終的name值。比如ClassPathResource類中的getDescription方法實現如下:
public String getDescription() {
StringBuilder builder = new StringBuilder("class path resource [");
String pathToUse = path;
if (this.clazz != null && !pathToUse.startsWith("/")) {
builder.append(ClassUtils.classPackageAsResourcePath(this.clazz));
builder.append('/');
}
if (pathToUse.startsWith("/")) {
pathToUse = pathToUse.substring(1);
}
builder.append(pathToUse);
builder.append(']');
return builder.toString();
}
上述的name處理邏輯暫時先有個印象即可,后續會詳細地跟蹤源碼進行講解。
1.2. PropertySource注解加載指定的屬性文件測試
上文我們設置了PropertySource注解來加載"classpath:config/jdbc-bainuo-dev.properties"文件。該文件的目錄結構如下圖所示:
jdbc-bainuo-dev.properties文件內容如下:
spring.datasource.shareniu.url=shareniu
application.properties文件內容如下:
spring.profiles.active=dev
上面的配置文件中,spring.profiles.active屬性配置了當前使用的環境是dev。spring.datasource.shareniu.url只是一個普通的屬性,本身並沒有什么特殊的含義。
下面開始書寫Springboot的啟動類,如下所示:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(DemoApplication.class);
ConfigurableApplicationContext configurableApplicationContext = springApplication.run(args);
CustomerDataSourceConfig1 customerDataSourceConfig = configurableApplicationContext
.getBean(CustomerDataSourceConfig1.class);
System.out.print(customerDataSourceConfig);
}
}
運行上述的代碼,程序的輸出如下:
CustomerDataSourceConfig{url='null'}
奇怪了,怎么url是空呢?PropertySource注解不是已經將jdbc-bainuo-dev.properties文件加載到當前的環境中了嗎?我們不妨試一下看看jdbc-bainuo-dev.properties中的spring.datasource.shareniu.url屬性是否可以獲取到,進而從側面驗證PropertySource注解已經將jdbc-bainuo-dev.properties文件加載到當前的環境中。修改上述啟動類的代碼如下:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(DemoApplication.class);
ConfigurableApplicationContext configurableApplicationContext = springApplication.run(args);
CustomerDataSourceConfig1 customerDataSourceConfig = configurableApplicationContext.getBean(CustomerDataSourceConfig1.class);
String property = configurableApplicationContext.getEnvironment().getProperty("spring.datasource.shareniu.url");
System.out.println(property);
System.out.print(customerDataSourceConfig);
}
}
運行上述的代碼,程序的輸出如下:
Shareniu
通過上述的代碼可以看出PropertySource確實是生效了。那么我們怎么將spring.datasource.shareniu.url屬性值自動注入到CustomerDataSourceConfig1 類中的url屬性中呢?
1.3. PropertySource注解讀取指定文件並將屬性注入到配置類
Spring中提供了@Value注解,用於將配置文件中的屬性值讀取出來並設置到相應的屬性中。在這里我們學習一下如何使用@Value注解。同樣的還是以上文的兩個類為例進行詳細說明,首先需要修改CustomerDataSourceConfig1類,修改部分如下所示:
@Component
@PropertySource( name="jdbc-bainuo-dev.properties",value= {"classpath:config/jdbc-bainuo-dev.properties"},ignoreResourceNotFound=false,encoding="UTF-8")
public class CustomerDataSourceConfig1 {
@Value("${spring.datasource.shareniu.url}")
private String url;
}
上述的類中,在url字段中增加了@Value注解,並指定了SPEL表達式為${spring.datasource.shareniu.url}。再次運行springboot啟動類,控制台的輸出為shareniu。表明確實可以通過@Value進行屬性值的注入。但是使用@Value注解方式有一個不太友好的地方就是,當項目中有大量的屬性進行配置的時候,我們需要一個個的在類的字段中增加@Value注解,這樣確實很費勁,不過我們可以通過Springboot提供的@ConfigurationProperties注解解決這個問題。
1.4. ConfigurationProperties注解使用
@ConfigurationProperties是類級別的注解,具體使用方式如下:
@Component
@ConfigurationProperties(prefix = "spring.datasource.shareniu")
@PropertySource( name="jdbc-bainuo-dev.properties",value= {"classpath:config/jdbc-bainuo-dev.properties"},ignoreResourceNotFound=false,encoding="UTF-8")
public class CustomerDataSourceConfig1 {
private String url;
}
上述代碼中,在CustomerDataSourceConfig1類中增加了ConfigurationProperties注解,並且指明了屬性的前綴為spring.datasource.shareniu。這樣Springboot在處理的時候,會去掃描當前類中的所有字段並進行屬性的查找以及組裝。比如我們配置的prefix = "spring.datasource.shareniu",CustomerDataSourceConfig1類中有一個url字段,則url字段需要匹配的屬性是prefix+字段=spring.datasource.shareniu.url。
那不僅有個疑問?如果指定的字段沒有找到屬性怎么辦呢?這個可以進行如下的配置:
@ConfigurationProperties(prefix = "spring.datasource.shareniu",ignoreUnknownFields=true,ignoreInvalidFields=true)
ignoreUnknownFields:忽略未知的字段。
ignoreInvalidFields:是否忽略驗證失敗的字段。這個怎么理解呢?比如我們在配置文件中配置了一個字符串類型的變量,類中的字段是int類型,那肯定會報錯的。如果出現這種情況我們可以容忍,則需要配置該屬性值為true。該參數值默認為false。
本文暫且講解到這里,后續的文章我們來講解@PropertySource注解如何實現讀取不同環境中的配置文件,這個不同環境的文件動態切換讀取,PropertySource默認是不支持的,因此我們需要擴展該注解對應的源碼。
————————————————
版權聲明:本文為CSDN博主「分享牛」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_30739519/java/article/details/78791142