前言
SpringBoot啟動時默認加載bootstrap.properties或bootstrap.yml(這兩個優先級最高)、application.properties或application.yml,如果我們配置了spring.profiles,同時會加載對應的application-{profile}.properties或application-{profile}.yml,profile為對應的環境變量,比如dev,如果沒有配置,則會加載profile=default的配置文件
雖然說配置項都寫在同一個配置文件沒有問題,但我們仍然希望能分開寫,這樣比較清晰,比如eureka的配置寫在eureka.properties,數據庫相關的配置寫在datasource.properties等等,因此就需要設置加載外部配置文件
更多關於配置項信息請看官網:https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#boot-features-external-config
本文記錄SpringBoot加載自定義配置文件的兩個方法
兩種方法
方法一
直接在具體的類上面使用注解加載
比如當你在ServiceAImpl需要使用到xxx.properties時
//手動加載自定義配置文件 @PropertySource(value = { "classpath:xxx.properties", }, encoding = "utf-8") @Service public class ServiceAImpl{ @Value("${cn.huanzi.qch.xxx}") private String xxx; }
如果你需要在更早一點引入,則可以在啟動類上進行引入
//手動加載自定義配置文件 @PropertySource(value = { "classpath:xxx.properties", "classpath:yyy.properties", "classpath:zzz.yml", }, encoding = "utf-8") @Component @SpringBootApplication public class SpringbootLoadmyprofilesApplication { public static void main(String[] args) { SpringApplication.run(SpringbootLoadmyprofilesApplication.class, args); } @Value("${cn.huanzi.qch.xxx}") private String xxx; @Value("${cn.huanzi.qch.yyy}") private String yyy; @Value("${cn.huanzi.qch.zzz}") private String zzz; @Bean void index(){ System.out.println(xxx); System.out.println(yyy); System.out.println(zzz); } }
如果我們只是在業務中需要用到自定義配置文件的值,這樣引入並沒有什么問題,但外部配置是一些啟動項,SpringBoot官網並不推薦我們這樣干
雖然在@SpringBootApplication上使用@PropertySource似乎是在環境中加載自定義資源的一種方便而簡單的方法,但我們不推薦使用它,因為SpringBoot在刷新應用程序上下文之前就准備好了環境。使用@PropertySource定義的任何鍵都加載得太晚,無法對自動配置產生任何影響。
這種情況下需要采用第二種方法
方法二
自定義環境處理類,在啟動之前定制環境或應用程序上下文,
Customize the Environment or ApplicationContext Before It Starts:https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#howto-customize-the-environment-or-application-context
官網還提供了一個列子:
我們也來寫一個自定義環境處理,在運行SpringApplication之前加載任意配置文件到Environment環境中
package cn.huanzi.qch.springbootloadmyprofiles; import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.PropertiesPropertySource; import org.springframework.core.env.PropertySource; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import java.io.IOException; import java.util.Properties; /** 自定義環境處理,在運行SpringApplication之前加載任意配置文件到Environment環境中 */ public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor { //Properties對象 private final Properties properties = new Properties(); @Override public void postProcessEnvironment(ConfigurableEnvironment environment,SpringApplication application) { //自定義配置文件 String[] profiles = { "xxx.properties", "yyy.properties", "zzz.yml", }; //循環添加 for (String profile : profiles) { //從classpath路徑下面查找文件 Resource resource = new ClassPathResource(profile); //加載成PropertySource對象,並添加到Environment環境中 environment.getPropertySources().addLast(loadProfiles(resource)); } } //加載單個配置文件 private PropertySource<?> loadProfiles(Resource resource) { if (!resource.exists()) { throw new IllegalArgumentException("資源" + resource + "不存在"); } try { //從輸入流中加載一個Properties對象 properties.load(resource.getInputStream()); return new PropertiesPropertySource(resource.getFilename(), properties); }catch (IOException ex) { throw new IllegalStateException("加載配置文件失敗" + resource, ex); } } }
並且在META-INF/spring.factories中
#啟用我們的自定義環境處理類
org.springframework.boot.env.EnvironmentPostProcessor=cn.huanzi.qch.springbootloadmyprofiles.MyEnvironmentPostProcessor
簡單測試
先看一下我們的工程結構
xxx、yyy、zzz里面就只有一個值(yyy、zzz就對應改成yyy、zzz)
cn.huanzi.qch.xxx=this is xxx
如果不手動加載自定義配置文件,啟動將會報錯
因為我們這里不是啟動項,方法一、方法二啟動效果都差不多
后記
部分代碼參考:https://www.jianshu.com/p/7ab1a62b04ed?from=timeline
代碼開源
代碼已經開源、托管到我的GitHub、碼雲: