什么是spring environment?

需求起因

最近在实现配置中心配置热更新时,想要有效的管理配置,并且与@Value,@ConfigurationProperties等spring 特性结合起来

这让我想起了spring boot 的 Externalized Configuration(外部化配置)

知识铺垫

为了避免照本宣科官方文档之嫌。这里列举几个本人认为最重要的外部配置源,spring boot将按一定顺序管理他们。

重要的外部配置源头说明
JAVA 系统变量java -D命令后的配置
操作系统环境变量
application.yml,application.properties文件

具体数据源超过10种,这里不在表述,在使用这些数据时,spring将按顺序使用他们,这就对配置数据实现缺省,覆盖需求提供了帮助

通过spring boot 的特性已知,PropertyResolver机制将直接使用spring boot外部配置源的数据完成配置的注入。

Spring Environment

所有的外部化配置,最终都被org.springframework.core.env.Environment管理

Environment的内部

environment内部管理着  org.springframework.core.env.PropertySource<T>

PropertySource以为Key-Value承载者具体的配置

所以,我们如果需要新增配置,修改配置,其实只需要操作Environment中的PropertySource即可。

配置顺序新增,删除,顺序调整

spring boot 的一个经典environment 是 org.springframework.core.env.StandardEnvironment

他的内部管理了PropertySource的集合对象org.springframework.core.env.MutablePropertySources

 

通过UML,可以看到关于调整配置项顺序的方法 addAfter(),addAtIndex(),addBefore(),

addFirst(),删除配置的方法 remove() 等

通过这些方法,可以方便的控制配置源的顺序,也可以将远程配置放入environment,配置中心配置刷新。

实例

public void loadRemoteConfig(){

            //伪代码 仅供参考,使用时请替换变量值


            //获取配置,可以通过配置中心获取
            String removeConfig = ""

            //转换配置数据为properties
            Properties properties = convert(removeConfig);

            if(properties!=null && properties.keySet().size()>0) {

                //构建一个PropertySource
                PropertySource p = new PropertiesPropertySource("配置源名称", properties);

                StandardEnvironment environment = (StandardEnvironment) this.environment;
                MutablePropertySources m = environment.getPropertySources();

                //将配置插入在 XXX配置源之前
                m.addBefore("XXX配置源",p);
            }
        

}

探索,Spring Environment何时初始化?

//SpringApplication.java
public ConfigurableApplicationContext run(String... args) {
		//省略若干行
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

            //构建spring environment,内部派发SpringApplicationRunListener事件
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);

			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
            
            //初始化spring 容器
			context = createApplicationContext();
			
            //省略若干行
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

由源码可知,spring environment初始化早于spring 容器的初始化,所以我们可以很方便的通过SpringApplicationRunListener事件来操作environment。

笔者自己就利用这个特性,在spring 容器初始化之前,加载默认配置和远程配置。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值