在Profile管理环境一文中介绍了环境的概念以及Spring Profile特性控制Bean的添加。本文将进一步介绍Spring管理和控制操作系统变量、JVM变量和Java标准资源(properties文件)的相关功能。
PropertySource与优先级
在整个JVM运行期间,我们可以随时随地获取到2个与环境相关的参数:
package chkui.springcore.example.hybrid.propertsource;
//env是与操作系统相关的参数
Map<String, String> env = System.getenv();
//properties中是Jvm相关的参数
Properties p = System.getProperties();
System.out.println("env :" + env);
System.out.println("properties :" + p);
如果没有人为的添加额外信息,
Spring会将操作系统参数和Jvm参数都整合到自己的环境管理接口Environment中,例如下面的代码:
package chkui.springcore.example.hybrid.propertsource;
//向系统级的properties设置一个参数
System.setProperty("wow", "World of Warcraft");
ApplicationContext ctx = new AnnotationConfigApplicationContext(PropertySourcesApp.class);
//通过spring的Environment获取参数
Environment springEnv = ctx.getEnvironment();
System.out.println(springEnv.getProperty("wow"));
System.out.println(springEnv.getProperty("PATH"));
除了我们自定义的"wow",操作系统参数"PATH"也可以在Spring的
通常情况下,在
除了通过外部设置,我们也可以直接使用Spring提供的接口来设置:
package chkui.springcore.example.hybrid.propertsource;
//我们要对环境进行配置,需要使用ConfigurableApplicationContext接口
ConfigurableApplicationContext configAbleCtx = new AnnotationConfigApplicationContext(PropertySourcesApp.class);
//ConfigurableApplicationContext接口提供对应的可编辑Environment和PropertySources
MutablePropertySources ps = configAbleCtx.getEnvironment().getPropertySources();
Map<String, Object> map = new HashMap<String, Object>();
map.put("wow", "Origin = World of Warcraft!But Edit it already!");
//添加到Spring的环境参数中
ps.addFirst(new MapPropertySource("myPropertySource", map));
System.out.println(springEnv.getProperty("wow"));
代码添加到
如果需要添加多个PropertySources,可以通过
引入资源文件
@PropertySource
在
package chkui.springcore.example.hybrid.propertsource;
@Configuration
@PropertySource("classpath:/hybrid/propertysource/config.properties")
public class PropertySourcesApp {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(PropertySourcesApp.class);
System.out.println("Properties file params: " + springEnv.getProperty("Gdi"));
}
}
对应的
#hybrid.propertysource.config.properties
Gdi=StarCraft
同一个工程中支持使用多个@PropertySource注解来引入配置文件,也支持Ant风格(Ant-style,例如"classpath:a/b/**/config.properties")以及Spring扩展的(比如"classpath*:")的路径规则,资源路径控制会在后续的文章中介绍。
XML配置
XML配置在之前介绍容器后置处理器——BeanFactoryPostProcessor的文章中已经介绍了,他就是
引入Bean:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!-- 指定*.properties文件的路径 -->
<property name="locations" value="classpath:/hybrid/propertysource/config.properties"/>
</bean>
直接使用context进行全局设置:
<context:property-placeholder location="classpath:/hybrid/propertysource/config.properties"/>
占位符替换
在Spring IoC容器执行Bean的扫描、加载之前添加一个环境变量(也可以动态添加然后再执行
@Configuration
//通过占位符来设置路径
@PropertySource("classpath:${resource.propertiesPath}/config.properties")
public class PropertySourcesApp {
public static void main(String[] args) {
//容器启动之前设置环境变量
System.setProperty("resource.propertiesPath", "/hybrid/propertysource");
ApplicationContext ctx = new AnnotationConfigApplicationContext(PropertySourcesApp.class);
//获取环境对象实例
Environment springEnv = ctx.getEnvironment();
System.out.println("Properties : " + springEnv.getProperty("Gdi"));
}
}
同样的,只要环境变量存在,也可以使用占位符替换配置文件中的数据,例如:
<context:property-placeholder location="classpath:${resource.propertiesPath:/config}/config.properties"/>
XML中的占位符使用的格式是
@Value
我们可以在任何Bean中使用@Value注解来获取环境变量。如下面的例子:
package chkui.springcore.example.hybrid.propertsource;
@Configuration
public class PropertySourcesApp {
@Value("${resource.propertiesPath}")
private String value;
@Value("#{systemProperties['resource.propertiesPath']}")
private String elValue;
@Value("Resource PropertiesPath")
private String staticValue;
public static void main(String[] args) {
System.setProperty("resource.propertiesPath", "/hybrid/propertysource");
ApplicationContext ctx = new AnnotationConfigApplicationContext(PropertySourcesApp.class);
PropertySourcesApp app = ctx.getBean(PropertySourcesApp.class);
System.out.println("Value: " + app.value);
System.out.println("EL Value: " + app.elValue);
System.out.println("Static Value: " + app.staticValue);
}
}
@Value可以注入一个纯字面量,如上面示例代码中的staticValue,也可以使用占位符使用环境变量中的任何值。除了使用占位符${},@Value还支持"#{systemProperties['resource.propertiesPath']}"这样具备代码执行功能的复杂表达式来获取数据,这部分功能会在后续介绍EL表达式的文章中进行分享。