科技改变生活 · 科技引领未来
在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
王楠东