SpringBoot載入額外配置檔案的兩種方式
阿新 • • 發佈:2020-11-14
一、為什麼要學額外配置檔案
本節為大家介紹另外一種場景:有一些老的專案裡面的jar包並未主動的去與spring boot 融合,很多jar包都有自己的配置檔案。如果我們在spring boot專案中使用這些jar包就必須得使用它們的配置檔案,那就面臨一個問題:我們的spring boot專案預設只有一個全域性配置檔案:application.yml或application.properties。該如何載入額外的配置檔案?
如何解決這個問題,就是本節將為大家介紹的內容。
二、使用@PropertySource載入自定義yml或properties檔案
2.1.@PropertySource註解載入properties配置檔案
family.properties
這種格式的配置檔案,在之前章節的程式碼基礎之上,使用如下的註解就可以將檔案中的配置屬性進行載入,非常簡單!
@PropertySource(value = {"classpath:family.properties"})
public class Family {
2.2.@PropertySource註解載入yaml配置檔案
但是這個註解只支援載入properties檔案,如何讓它載入yml格式的檔案呢?
spring 官方文件明確說明不支援使用@PropertySource載入YAML配置檔案,但是我們仍然有辦法,跟著我繼續。
- 我們新建一個配置檔案family.yml,把上一節用到的YAML資料結構放裡面。用來模擬第三方jar包的額外配置檔案(非application配置檔案)。
# 新建一個配置檔案family.yml, # 把上一節用到的YAML資料結構放裡面。用來模擬第三方jar包的額外配置檔案(非application配置檔案)。 # 如果主配置檔案中也有family屬性的話,就走主配置檔案當中的,不會走我們這個! family: family-name: "happy family" father: name: zhoujinyuan beat: ${family.father.name:zhoujinyuan2} age: 24 mother: alias: - aaa - bbb child: name: leijieqiong age: ${random.int} friends: - {hobby: football,sex: male} - {hobby: basketball,sex: female}
- 筆者通過閱讀程式碼瞭解到,DefaultPropertySourceFactory是進行配置檔案載入的工廠類。
- 儘管其預設不支援讀取YAML格式外部配置檔案,但是我們可以通過繼承DefaultPropertySourceFactory ,然後對它的createPropertySource進行一下改造。就可以實現YAML的“額外”配置檔案載入。
package com.zhoujinyuan.springbootyml.util;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.ResourcePropertySource;
import org.springframework.lang.Nullable;
import java.io.IOException;
import java.util.Properties;
/**
* 實現YAML的“額外”配置檔案載入。
* ·@PropertySource· 註解預設不支援載入yml配置檔案
* 自定義一個類繼承DefaultPropertySourceFactory ,然後對它的createPropertySource進行一下改造。就可以實現YAML的“額外”配置檔案載入。
*/
public class MixPropertySourceFactory extends DefaultPropertySourceFactory {
/**
* 改造實現YAML的“額外”配置檔案載入。
*
* @param name 我們資原始檔的名字
* @param resource 編碼資源的一個物件
* @return
* @throws IOException
*/
public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException {
// return name != null ? new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource);
String sourceName = name != null ? name : resource.getResource().getFilename();
//如果是yml格式配置檔案就先轉成properties檔案格式再走父類方法就好了。
if (sourceName != null &&(sourceName.endsWith(".yml") || sourceName.endsWith(".yaml"))) {
Properties propertiesFromYaml = loadYml(resource);
//將YML配置轉成Properties之後,再用PropertiesPropertySource繫結
return new PropertiesPropertySource(sourceName, propertiesFromYaml);
} else {
//如果是Properties檔案就預設走父類方法處理就好了。
return super.createPropertySource(name, resource);
}
}
//將YML格式的配置轉成Properties配置
private Properties loadYml(EncodedResource resource) throws IOException{
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return factory.getObject();
}
}
- 然後基於上一節的程式碼,在Family類的上面加上如下註解即可。通過factory屬性明確的指定使用我們自定義的MixPropertySourceFactory載入yml配置檔案。
@Data
@Component // 必須加入容器內才能讀取配置檔案資訊
@ConfigurationProperties(prefix = "family") //接收yml配置的java實體類,表示配置的整體字首
@Validated // 使主實體類以下的成員帶有校驗註解的都生效。(開啟校驗功能的)
@PropertySource(value = {"classpath:family.yml"}, factory = MixPropertySourceFactory.class) // 作用:載入配置檔案的,預設只支援properties格式的。屬性value:指明配置檔案位置。屬性factory:指定使用我們自定義的MixPropertySourceFactory載入yml配置檔案。
public class Family {
//@Value("${family.family-name}")
@NotEmpty
private String familyName; //成員變數名稱要和yml配置項key一一對應
private Father father;
private Mother mother;
private Child child;
}
三、使用@ImportResource載入Spring的xml配置檔案
在沒有Spring註解的時代,spring的相關配置都是通過xml來完成的,如:XXX.xml。下面的XML配置的含義是:將com.zhoujinyuan.springbootyml.service.TestService例項化並注入到Spring上下文環境中。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--測試SpringBoot載入XML格式配置檔案-->
<bean class="com.zhoujinyuan.springbootyml.service.TestService" id="testService"></bean>
</beans>
- 新建一個空類,com.zhoujinyuan.springbootyml.service.TestService。
- 測試用例,測試Spring上下文環境中是否有TestService這樣一個bean,有的話表示xml配置檔案已經生效,成功將testService例項化並注入到Spring上下文環境中:
@SpringBootTest
public class SpringbootYmlApplicationTests{
@Autowired
ConfigurableApplicationContext applicationContext;
@Test
public void test2(){
//測試Spring上下文環境中是否有testBeanService這樣一個bean,有的話表示xml配置檔案生效
Boolean bean = applicationContext.containsBean("testService");
System.out.println(bean);
}
}
- 因為還沒使用@ImportResource載入XXX.xml,此時執行測試用例,輸出false表示XXX.xml配置檔案並未載入,所以沒有testService的存在
- 在spring boot應用入口啟動類上加
@ImportResource(locations = {"classpath:XXX.xml"})
,該註解用來載入Spring XML配置檔案。
此時再試一下測試用例,輸出:true。表示XXX.xml配置檔案被正確載入。
@SpringBootApplication
@ImportResource(locations = {"classpath:XXX.xml"})
public class SpringbootYmlApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootYmlApplication.class, args);
}
}
輸出為true。