科技改變生活 · 科技引領未來
在springboot中environment主要用來保存我們的配置,它主要包括兩個方面,profiles 和 properties。profiles指的就是我們的多環境(開發,測試,生成等),切換不同的profiles就會切換不同的bean和配置文件。而properties 就是我們經常使用的key-value鍵值對集合。
application.run方法
上圖就是springboot應用啟動過程,包括創建environment,準備創建context,發布監聽事件,啟動runers (ApplicationRunner、commandLineRunner等啟動器)。
getOrCreateEnvironment 整個過程包括創建和配置environment,以及發布environment準備通知事件,我們可以通過監聽此事件在代碼中新增或者更改我們的environment的環境變量。
1、創建ConfigurableEnvironment。如果是WebApplicationType.SERVLET 就會返回StandardServletEnvironment,因為我們都是springboot web應用程序所以這里返回StandardServletEnvironment。
private ConfigurableEnvironment getOrCreateEnvironment() { if (this.environment != null) { return this.environment; } if (this.webApplicationType == WebApplicationType.SERVLET) { return new StandardServletEnvironment(); } return new StandardEnvironment();}
初始創建的environment
初始創建的environment
2、configureEnviroment配置environment。這里配置包括上面一節提到過的兩個功能—property和profiles。這里面只做了初始化的功能,這里并未真正的加載例如application.properties/yml的propeties以及profile。
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) { configurePropertySources(environment, args); configureProfiles(environment, args);}
3、發布environmentPrepared的ApplicationEnvironmentPreparedEvent事件。
public void environmentPrepared(ConfigurableEnvironment environment) { for (SpringApplicationRunListener listener : this.listeners) { listener.environmentPrepared(environment); }}@Overridepublic void environmentPrepared(ConfigurableEnvironment environment) {this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));}
ApplicationEnvironmentPreparedEvent的監聽器
首先會獲取到所有的監聽器,然后觸發這些監聽器,這里我們以ConfigFileApplicaationListener
為例,ConfigFileApplicationListener會讀取配置文件,并加載到environment中的PropertySources列表中。首先會加載當前激活的profile列表,然后從classpath:/,classpath:/config/,file:./,file:./config/ 找到 application-{profile}的配置文件(可通過spring.config.location 配置文件搜索路徑)。
處理environmentPreparedEvent的判斷邏輯
** 代碼獲取所有監聽器,遍歷循環,執行postProcessEnvironment后置處理 ** private void onApplicationEnvironmentPreparedEvent( ApplicationEnvironmentPreparedEvent event) { List postProcessors = loadPostProcessors(); postProcessors.add(this); ConfigFileApplicationListener本身也是postProcessor AnnotationAwareOrderComparator.sort(postProcessors); for (EnvironmentPostProcessor postProcessor : postProcessors) { postProcessor.postProcessEnvironment(event.getEnvironment(), event.getSpringApplication()); }}
4、幾個常見監聽器處理邏輯
SystemEnvironmentPropertySourceEnvironmentPostProcessor:替換系統的環境變量USERDOMAIN_ROAMINGPROFILE -> LLS,JAVA_HOME -> C:Program FilesJavajdk1.8.0_151等。
ConfigFileApplicationListener:添加RandomValuePropertySource,加載profile 例如‘dev’ ,根據這個dev profile環境,加載config文件的property source到environment。下圖所示即已加載了多個PropertySource(random、applicaton-docker-dev.yml、application-properties等)
已加載至環境中的PropertySources
擴展:自定義EnvironmentPostProcessor
springboot提供EnvironmentPostProcessor接口用于environment后處理。在實現postProcessEnvironment的方法中可以加載任何想需要的屬性到environment中。
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { Properties pros = new Properties(); pros.setProperty(&34;woshiyizhiwugui&34;, &34;我是一個小烏龜&34;); PropertiesPropertySource propertiesPropertySource = new PropertiesPropertySource(fileName, pros); environment.getPropertySources().addLast(propertiesPropertySource);environment.setRequiredProperties(&34;helloworld&34;); //設置必須要有的屬性,如果未配置,springboot啟動異常}
dubbo擴展的DubboDefaultPropertiesEnvironmentPostProcessor
王楠東