文档章节

Spring核心——资源数据管理

随风溜达的向日葵
 随风溜达的向日葵
发布于 08/01 10:26
字数 1406
阅读 2874
收藏 52

Profile管理环境一文中介绍了环境的概念以及Spring Profile特性控制Bean的添加。本文将进一步介绍Spring管理和控制操作系统变量、JVM变量和Java标准资源(properties文件)的相关功能。

文章的代码仅仅用于说明问题,可执行代码请到我的gitee库clone,本文的代码在chkui.springcore.example.hybrid.propertsource包中。

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);

如果没有人为的添加额外信息,System::getEnv获取的数据都与当前的操作系统相关(以下称为“操作系统参数”),而System::getProperties获取的内容都与Jvm相关(以下称为“JVM参数”)。

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的Environment中获取。

通常情况下,在Environment内部维护了2个PropertySources的实例:一个是操作系统参数,另外一个是JVM参数。如果2者有同样的参数,那么我们在调用Environment::getProperty方法时,得到的是JVM参数(System::getProperties),也就是说 Jvm参数具有更高的优先级。

除了通过外部设置,我们也可以直接使用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"));

代码添加到PropertySource中,Environment会额外维护一个PropertySources,而自己添加的PropertySources优先级是最高的,所以最后Environment::getProperty获取到的值是最后设置的值。

如果需要添加多个PropertySources,可以通过MutablePropertySources::addFirstMutablePropertySources::addLast方法来控制他们之间的优先级。

引入资源文件

*.properties是Java的标准资源文件,在Java的各种项目中常用来记录各种配置参数。Spring提供了注解和XML配置将*.properties文件中的数据整合到Spring的环境参数(Environment)中。

@PropertySource

@Configuration标记的类上使用@PropertySource注解可以引入0~n个*.properties配置文件。如下面的例子:

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"));
	}
}

对应的config.properties文件:

#hybrid.propertysource.config.properties

Gdi=StarCraft

同一个工程中支持使用多个@PropertySource注解来引入配置文件,也支持Ant风格(Ant-style,例如"classpath:a/b/**/config.properties")以及Spring扩展的(比如"classpath*:")的路径规则,资源路径控制会在后续的文章中介绍。

XML配置

XML配置在之前介绍容器后置处理器——BeanFactoryPostProcessor的文章中已经介绍了,他就是 PropertyPlaceholderConfigurer ,我们在XML配置文件中进行一下设置即可。

引入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"/>

占位符替换

PropertyPlaceholderConfigurer继承了抽象类PropertyPlaceholderConfigurer,*.properties文件的读写就是在PropertyResourceConfigurer类中实现的。PropertyPlaceholderConfigurer进一步实现了配置文件中占位符(${...})替换功能

在Spring IoC容器执行Bean的扫描、加载之前添加一个环境变量(也可以动态添加然后再执行ConfigurableApplicationContext::refresh方法),就可以在很多资源路径的位置使用这个占位符,对上面的例子进行一些修改:

@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中的占位符使用的格式是${resource.propertiesPath:/config},它表示使用环境变量resource.propertiesPath进行替换,如果resource.propertiesPath不存在则使用值"/config"。

@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表达式的文章中进行分享。

© 著作权归作者所有

共有 人打赏支持
随风溜达的向日葵
粉丝 275
博文 77
码字总数 166662
作品 0
广州
其他
私信 提问
加载中

评论(1)

RomeoZhou
RomeoZhou
你好,wow玩家
【死磕 Spring】—– IOC 之 IOC 初始化总结

原文出自:http://cmsblogs.com 前面 13 篇博文从源码层次分析了 IOC 整个初始化过程,这篇就这些内容做一个总结将其连贯起来。 在前文提过,IOC 容器的初始化过程分为三步骤:Resource 定位...

chenssy
10/09
0
0
Spring核心——FactoryBean

本文继续之前的2篇文章(BeanPostProcessor和BeanFactoryPostProcessor)介绍Ioc容器的功能扩展。 FactoryBean是用来构造Bean的接口。常规情况下向容器添加一个Bean只需要像下面这样通过XML...

随风溜达的向日葵
07/12
0
0
Spring(一)——总体介绍

工作闲着,快速回顾一下spring框架。Spring框架,是进行对象管理,对象关联,解耦的一个中间层框架。SSH(Struts+Spring+Hibernate)三大Spring在中间就起着一个承上启下的作用。好,首先我们...

凡尘里的一根葱
2015/11/10
0
0
Spring核心——字符串到实体转换

笼统的说一个系统主要是由3个部分组成的: 执行程序:主要负责处理业务逻辑,对接用户操作。 内部数据:嵌套在源码中的数据,用于指导程序运行。 外部数据:业务数据,外部配置数据。 内部数...

随风溜达的向日葵
09/06
0
0
Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密...

小致dad
08/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

EOS docker开发环境

使用eos docker镜像是部署本地EOS开发环境的最轻松愉快的方法。使用官方提供的eos docker镜像,你可以快速建立一个eos开发环境,可以迅速启动开发节点和钱包服务器、创建账户、编写智能合约....

汇智网教程
今天
12
0
《唐史原来超有趣》的读后感优秀范文3700字

《唐史原来超有趣》的读后感优秀范文3700字: 作者:花若离。我今天分享的内容《唐史原来超有趣》这本书的读后感,我将这本书看了一遍之后就束之高阁了,不过里面的内容一直在在脑海中回放,...

原创小博客
今天
19
0
IC-CAD Methodology知识图谱

CAD (Computer Aided Design),计算机辅助设计,指利用计算机及其图形设备帮助设计人员进行设计工作,这个定义同样可以用来近似描述IC公司CAD工程师这个岗位的工作。 早期IC公司的CAD岗位最初...

李艳青1987
今天
18
0
CompletableFuture get方法一直阻塞或抛出TimeoutException

问题描述 最近刚刚上线的服务突然抛出大量的TimeoutException,查询后发现是使用了CompletableFuture,并且在执行future.get(5, TimeUnit.SECONDS);时抛出了TimeoutException异常,导致接口响...

xiaolyuh
今天
9
0
dubbo 搭建与使用

官网:http://dubbo.apache.org/en-us/ 一,安装监控中心(可以不安装) admin管理控制台,monitor监控中心 下载 bubbo ops 这个是新版的,需要node.js环境,我没有就用老版的了...

小兵胖胖
今天
19
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部