Spring 系列目录(http://www.javashuo.com/article/p-kqecupyl-bm.html)html
Spring 3.1 提供了新的属性管理 API,并且功能很是强大且很完善,对于一些属性配置信息都应该使用新的 API 来管理。位于 org.springframework.core.env
包内。java
Spring Environment 属性配置管理系列文章:web
PropertySource
:属性源,key-value 属性对抽象,好比用于配置数据PropertyResolver
:属性解析器,用于解析相应 key 的 valueEnvironment
:环境,自己是一个 PropertyResolver,可是提供了 Profile 特性,便可以根据环境获得相应数据(即激活不一样的 Profile,能够获得不一样的属性数据,好比用于多环境场景的配置(正式机、测试机、开发机 DataSource 配置)Profile
:剖面,只有激活的剖面的组件/配置才会注册到 Spring 容器,相似于 maven 中 profile也就是说,新的 API 主要从配置属性、解析属性、不一样环境解析不一样的属性、激活哪些组件/配置进行注册这几个方面进行了从新设计,使得 API 的目的更加清晰,并且功能更增强大。spring
@Test public void test() { Environment env = new StandardEnvironment(); // 1. 操做系统的环境变量 Map<String, Object> systemEnvironment = ((StandardEnvironment) env).getSystemEnvironment(); Assert.assertNotNull(systemEnvironment); // 2. JVM 属性配置 Map<String, Object> systemProperties = ((StandardEnvironment) env).getSystemProperties(); Assert.assertNotNull(systemProperties); // 3. 属性 Assert.assertEquals("UTF-8", env.getProperty("file.encoding")); Assert.assertTrue(env.containsProperty("file.encoding")); // 4. 剖面 spring.profiles.default(默认为 default) spring.profiles.active // 只要有一个返回 true acceptsProfiles 方法就返回 true,!a 为不包含该 profiles Assert.assertTrue(env.acceptsProfiles("default")); Assert.assertTrue(env.acceptsProfiles("a", "default")); Assert.assertFalse(env.acceptsProfiles("a")); Assert.assertTrue(env.acceptsProfiles("!a", "b")); }
public abstract class PropertySource<T> { // 给数据源起个名称 protected final String name; // 数据源,可能为 Map 或 Properties ... protected final T source; public boolean containsProperty(String name) { return (getProperty(name) != null); } public abstract Object getProperty(String name); }
PropertySource 很是相似于 Map,数据源可来自 Map、Properties、Resource 等。PropertySource 接口有两个特殊的子类:StubPropertySource 用于占位用,ComparisonPropertySource 用于集合排序,不容许获取属性值。数据库
MapPropertySource 的属性来自于一个 Map,而 ResourcePropertySource 的属性来自于一个 properties 文件,另外还有如 PropertiesPropertySource,其属性来自 Properties,ServletContextPropertySource 的属性来自 ServletContext 上下文初始化参数等等,你们能够查找 PropertySource 的继承层次查找相应实现。api
@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 提供了组合 PropertySource 的功能,查找顺序就是注册顺序。spring-mvc
@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,从名字能够看出其包含多个 PropertySource。默认提供了一个 MutablePropertySources 实现,能够调用 addFirst 添加到列表的开头,addLast 添加到末尾,另外能够经过 addBefore(propertySourceName, propertySource) 或 addAfter(propertySourceName, propertySource) 添加到某个 propertySource 前面/后面;最后你们能够经过 iterator 迭代它,而后按照顺序获取属性。mvc
注意:PropertySource 的顺序很是重要,由于 Spring 只要读到属性值就返回。app
@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")); }
到目前咱们已经有属性了,接下来须要更好的 API 来解析属性了。框架
PropertyResolver 的使用参考:http://www.javashuo.com/article/p-pgbhqkkt-bs.html
Environment 是对 JDK 环境、Servlet 环境、Spring 环境的抽象;每一个环境都有本身的配置数据,如 System.getProperties()、System.getenv() 等能够拿到 JDK 环境数据;ServletContext.getInitParameter()能够拿到 Servlet 环境配置数据等等;也就是说 Spring 抽象了一个 Environment 来表示环境配置。
public interface Environment extends PropertyResolver { String[] getActiveProfiles(); String[] getDefaultProfiles(); // @since 5.1 废弃,改用 Profiles(Profiles.of("dev")) @Deprecated boolean acceptsProfiles(String... profiles); boolean acceptsProfiles(Profiles profiles); }
从 API 上能够看出,除了能够解析相应的属性信息外,还提供了剖面相关的 API。目的是:能够根据剖面有选择的进行注册组件/配置。好比对于不一样的环境注册不一样的组件/配置(正式机、测试机、开发机等的数据源配置)。它的主要几个实现以下所示:
MockEnvironment
:模拟的环境,用于测试时使用;StandardEnvironment
:标准环境,普通 Java 应用时使用,会自动注册 System.getProperties() 和 System.getenv()到环境;StandardServletEnvironment
:标准 Servlet 环境,其继承了 StandardEnvironment,Web 应用时使用,除了 StandardEnvironment 外,会自动注册 ServletConfig(DispatcherServlet)、ServletContext 及 JNDI 实例到环境;<context-param> <param-name>myConfig</param-name> <param-value>hello</param-value> </context-param> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> </servlet>
使用 StandardServletEnvironment 加载时,默认除了 StandardEnvironment 的两个属性外,还有另外三个属性:servletContextInitParams(ServletContext)、servletConfigInitParams(ServletConfig)、jndiProperties(JNDI)。
(1) 注解
@Autowired Environment env;
(2) ApplicationContext
applicationContext.getEnvironment();
profile 剖面,大致意思是:咱们程序可能从某几个剖面来执行应用,好比正式机环境、测试机环境、开发机环境等,每一个剖面的配置可能不同(好比开发机可能使用本地的数据库测试,正式机使用正式机的数据库测试)等;所以呢,就须要根据不一样的环境选择不一样的配置;若是 maven 中的 profile 的概念。
profile 有两种:
查找顺序是:先进性明确激活的匹配,若是没有指定明确激活的(即集合为空)就找默认的;配置属性值从 Environment 读取。
profile 设置方式常见的有三种:
(1) -D 传入系统参数
-Dspring.profiles.active=dev
(2) web 环境
<context-param> <param-name>spring.profiles.active</param-name> <param-value>dev</param-value> </context-param>
(3) xml 配置
经过在 beans 标签上加上 profile 属性,这样当咱们激活相应的 profile 时,此 beans 标签下的 bean 就会注册,以下所示:
<beans> <beans profile="dev"> <bean id="dataSource" class="..."> </bean> </beans> <beans profile="test"> <bean id="dataSource" class="..."> </bean> </beans> </beans>
启动应用时设置相应的 "spring.profiles.active" 便可。另外,若是想指定一个默认的,可使用
(4) 注解配置
Java Config 方式的 Profile,功能等价于 XML 中的
@Profile("dev") @Configuration @PropertySource(value = "classpath:resources.properties", ignoreResourceNotFound = false) public class AppConfig { @Bean public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } }
Spring4 提供了一个新的 @Conditional 注解,请参考 http://jinnianshilongnian.iteye.com/blog/1989379
(5) @ActiveProfiles()
在测试时,有时候不能经过系统启动参数/上下文参数等指定 Profile,此时 Spring 测试框架提供了 @ActiveProfiles() 注解,示例以下:
@ActiveProfiles("test") @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = GenericConfig.class) public class GenricInjectTest { }
到此整个 Spring 的属性管理 API 就介绍完了,对于属性管理,核心是 Environment。
参考:
天天用心记录一点点。内容也许不重要,但习惯很重要!