概述
Environment 这个接口代表应用运行时的环境。它代表了两方面、一个是 profile 一个是 properties。访问 property 的方法通过 Environment 继承的接口 PropertyResolver 暴露出去。
根据 profile 是否被激活、控制着哪些 bean 的信息会被注册到 Spring 的容器中。Environment 的作用就是提供获取当前哪些 profile 被激活、哪些 profile 是默认被激活的方法。
properties 的来源有以下的几个方面
- properties 文件
- JVM 系统属性
- 系统环境变量
- JNDI
- Servlet 上下文变量
environment 为用户提供了简易的接口让用户去配置属性源(property source) 并且从属性源中解释属性出来。
PropertyResolver
除了常规的方法、有两个挺有一些的方法、用于解释 SPEL 表达式、当然只是 ${}的、如果想要解释 #{} 的、可以使用 StringValueResolver 解释。
PropertySource
PropertySource 非常类似于 Map,数据源可来自 Map、Properties、Resource 等。PropertySource 接口有两个特殊的子类:StubPropertySource 用于占位用,ComparisonPropertySource 用于集合排序,不允许获取属性值。
@Test
public void PropertySourceTest() throws IOException {
PropertySource mapPropertySource = new MapPropertySource("map",
Collections.singletonMap("key", "source1"));
Assert.assertEquals("value1", mapPropertySource.getProperty("key"));
ResourcePropertySource resourcePropertySource = new ResourcePropertySource(
"resource", "classpath:resources.properties");
Assert.assertEquals("value2", resourcePropertySource.getProperty("key"));
}
CompositePropertySource
CompositePropertySource 提供了组合 PropertySource 的功能,查找顺序就是注册顺序。
@Test
public void CompositePropertySourceTest() throws IOException {
PropertySource propertySource1 = new MapPropertySource("source1",
Collections.singletonMap("key", "value1"));
PropertySource propertySource2 = new MapPropertySource("source2",
Collections.singletonMap("key", "value2"));
CompositePropertySource compositePropertySource = new CompositePropertySource("composite");
compositePropertySource.addPropertySource(propertySource1);
compositePropertySource.addPropertySource(propertySource2);
Assert.assertEquals("value1", compositePropertySource.getProperty("key"));
}
PropertySources
另外还有一个 PropertySources,从名字可以看出其包含多个 PropertySource。默认提供了一个 MutablePropertySources 实现,可以调用 addFirst 添加到列表的开头,addLast 添加到末尾,另外可以通过 addBefore(propertySourceName, propertySource) 或 addAfter(propertySourceName, propertySource) 添加到某个 propertySource 前面/后面;最后大家可以通过 iterator 迭代它,然后按照顺序获取属性。
注意:PropertySource 的顺序非常重要,因为 Spring 只要读到属性值就返回。
@Test
public void PropertySourcesTest() throws IOException {
PropertySource propertySource1 = new MapPropertySource("source1",
Collections.singletonMap("key", "value1"));
PropertySource propertySource2 = new MapPropertySource("source2",
Collections.singletonMap("key", "value2"));
MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addFirst(propertySource1);
propertySources.addLast(propertySource2);
Assert.assertEquals("value1", propertySources.get("source1").getProperty("key"));
Assert.assertEquals("value2", propertySources.get("source2").getProperty("key"));
}
Environment
其主要实现类是 AbstractEnvironment 中
StandardEnvironment 覆盖父类设置属性源的方法、向其增加系统属性和系统环境变量的属性源。
而StandardServletEnvironment 则是增加了 servlet相关的两个属性源、并且实现了初始化属性源的方法。将
StubPropertySource 替换为 servlet 相关的属性源。
大体上就是这样吧、一直不太理解 Environment 到底是何物、大概知道了现在。