概述
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 到底是何物、大概知道了現在。