原文地址:http://www.summa.com/blog/2009/04/20/6-tips-for-managing-property-files-with-spring

What could be simpler than property files? In an enterprise application, it turns out, many things! In this post I’ll take a look at a few subtle complexities to managing properties in an enterprise Java Spring application, and hopefully demonstrate how a little fore-thought in design can yield big savings in terms of time, confusion, bugs, and gray hair down the road.

Types of Properties

Before designing an approach to managing property files, it's critical first to understand the types of properties are to be managed. Here are four characteristics to consider:

    • Are some properties environment specific – in other words, do they have a different value in one environment than another? For example, a database connection string would differ in the TEST environment than it would the PROD environment.
    • Do any properties contain sensitive information, like passwords or credentials, that can’t sit in plain text in the deployment unit (e.g. WAR, EAR)?
    • Do any properties need to be located external from the deployment unit (e.g. on the file system rather than in the WAR, perhaps to be managed by a systems administrator)?
    • Should properties be dynamic, in the sense that they can be updated at runtime (i.e. without requiring a restart of the application)?

Each of these special characteristics adds a degree of complexity to applications - necessitating additional infrastructure beyond the simple Java Properties class.

Spring’s PropertyPlaceholderConfigurer

Fortunately for us, the Spring framework, with the PropertyPlaceholderConfigurer and PropertyOverrideConfigurer, provides the features and hooks we need to manage these cases (with the exception “dynamic” properties). And true to its philosophy, Spring makes simple things simple, and complicated things possible.

The PropertyPlaceholderConfigurer allows properties to be pulled in to the application context file. For example, in the simplest case, a property “db.user” defined in database.properties could be pulled into the ${db.user} placeholder:

<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:database.properties</value>
</list>
</property>
</bean> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${db.user}"/>
<property name="password" value="${db.password}"/>
...
</bean>

The PropertyOverrideConfigurer works in the opposite way, pushing properties from property files into properties in the context file (without having to specifically define a place holder – e.g. ${db.user}). These are both well documented in the Spring API and documentation.

Tips

Given the different possible types of properties, and Spring's property framework, here are a few tips for managing them:

1) Consider using a JVM System property that sets the environment of the machine (e.g. "my.env=TEST"), telling the configurer which property file to use. For example:

  <context:property-placeholder
location="classpath:db-${my.env}.properties"/>

If the "my.env" property was set to "TEST", then obviously the PropertyPlacementConfigurer would look for a file called "db-TEST.properties". For Tomcat, this property can be set in the admin console or defined in a startup script (e.g. "-Dmy.env=TEST") - neither of which is very elegant. Alternatively, it is possible to use JNDI with Tomcat, defining "my.env" in the server.xml and the context.xml of the web app. (Note, there are of course many other ways to solve this environment-specific problem, but this is an easy and relatively straight-forward one.)

2) It may be necessary to set the ignoreUnresolvablePlaceholders to true for any PropertyPlaceholderConfigurer, which will ensure that a configurer won’t fail if it can’t find a property. Why would this be a good thing? Oftentimes, one context file will import other context files, and each may have their own configurer. If ignoreUnresolvablePlaceholders is set to false (the default), then one configure would fail if it couldn’t find the property, even if another configurer down-stream could find it (see good explanation here). Beware, however, since this will suppress warnings for legitimate missing properties, making for some tough-to-debug configuration problems.

3) To encrypt properties, subclass the PropertyPlacementConfigurer and override the convertPropertyValue() method. For example:

protected String convertPropertyValue(String strVal) {
//if strVal starts with “!!” then return EncryptUtil.decrypt(strVal)
// else return strVal
}

4) Consider using the systemPropertiesMode property of the configurer to override properties defined in property files with System properties. For one-off environment specific properties this can be a helpful solution, however, for defining many properties, this configuration can be cumbersone.

5) For properties that need to be managed outside of the WAR, consider using a System property to define where the file is located. For example, the property ${ext.prop.dir} could define some default directory on the file system where external property files are kept:

<context:property-placeholder
location="file:///${ext.prop.dir}db.properties"/>

This entails, however, that this property is set for any process that leverages the Spring container (e.g. add the param to the Run Configurationfor integration/unit tests, etc.), otherwise the file would not be found. This can be a pain. To circumvent, the configurer can be overridden – changing the behavior such that it looks to the external directory only if the System property is set, otherwise it pulls from the classpath.

6) Beware of redundancy of environment-specific properties. For example, if the solution is to have one property file for each environment (e.g. “db-test.properties”, “db-dev.properties”, etc.), then maintaining these properties can be a bit of a nightmare - if a property "foo" is added, then it would have to be added to the property file for each environment (e.g. DEV, TEST, PROD, etc.). The PropertyOverrideConfigurer is appropriate to eliminate this redundancy, setting the default value in the application context itself, but then the overriding value in a separate file. It's important, however, to document this well, since it can look a bit "magical" to an unsuspecting maintenance developer who sees one value specified in the context file, but another used at runtime.

Conclusion

Managing properties for an enterprise application is a little trickier than one might expect. With Spring's property configurers, however, the toughest part is just knowing what you need - the rest comes out of the box, or with some minor extensions.

Hopefully a few of these tips will be useful for you. Please let me know some of your own!

6-tips-for-managing-property-files-with-spring--转的更多相关文章

  1. Spring property文件配置方法以及如何与工程分离

    1,Spring使用property文件作为配置源    工程中难免出现一些需要每次部署都需要配置的参数,如数据源连接参数等,测试环境跟实际运行环境是不一样的.    使用spring框架的话,这些参 ...

  2. spring boot中的底层配置文件application.yam(application.property)的装配原理初探

    *在spring boot中有一个基础的配置文件application.yam(application.property)用于对spring boot的默认设置做一些改动. *在spring boot ...

  3. 译:Spring框架参考文档之IoC容器(未完成)

    6. IoC容器 6.1 Spring IoC容器和bean介绍 这一章节介绍了Spring框架的控制反转(IoC)实现的原理.IoC也被称作依赖注入(DI).It is a process wher ...

  4. Spring Boot Reference Guide

    Spring Boot Reference Guide Authors Phillip Webb, Dave Syer, Josh Long, Stéphane Nicoll, Rob Winch,  ...

  5. spring官网在线学习文档翻译

    Core Technologies (核心技术) Version 5.0.8.RELEASE 版本5.0.8RELEASE This part of the reference documentati ...

  6. spring源码分析之<context:property-placeholder/>和<property-override/>

    在一个spring xml配置文件中,NamespaceHandler是DefaultBeanDefinitionDocumentReader用来处理自定义命名空间的基础接口.其层次结构如下: < ...

  7. Spring:源码解读Spring IOC原理

    Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. I ...

  8. Spring Boot文档阅读

    原因之初 最初习惯百度各种博客教程,然后跟着操作,因为觉得跟着别人走过的路走可以少走很多弯路,省时间.然而,很多博客的内容并不够完整,甚至错误,看多了的博客甚至有千篇一律的感觉.此外,博客毕竟是记载博 ...

  9. 玩转spring boot——properties配置

    前言 在以往的java开发中,程序员最怕大量的配置,是因为配置一多就不好统一管理,经常出现找不到配置的情况.而项目中,从开发测试环境到生产环境,往往需要切换不同的配置,如测试数据库连接换成生产数据库连 ...

随机推荐

  1. tomcat之Session的管理

    Session是由服务器端的应用服务器容器(如Tomcat.Jetty)存储的.下面分析一下Tomcat是如何管理Session的. 转自:tomcat架构分析 (Session管理) Tomcat中 ...

  2. GIT 版本控制常用命令学习汇总

    GIT 版本控制常用命令汇总 git version 查看当前git版本信息 git help 获取全部命令帮助信息 git help <command> 获取指定命令帮助信息 git c ...

  3. .Net程序员之不学Java做安卓开发:奇怪的Java语法

    1.final关键字:用以修饰类时,表示类不可以被继承,指向基本数据类型或者引用类型时,该类只可以在声明的时候初始化 2.@Override 类似C# 中override关键字,表示对父类的重写.网上 ...

  4. 谢欣伦 - 原创软件 - 游戏专题 - 操蛋的小鸟Fucking Bird

    前段时间朋友介绍了一个最近很火的游戏<Flappy Bird>.在工作之余,我用了三天时间做了一个类似的游戏<Fucking Bird>.一开始分享给了两个女同事,发现她们玩嗨 ...

  5. 使用Javascript来实现二级联动菜单的效果

    效果图如下: 具体实现步骤如下: 1.所用js代码如下: <script type="text/javascript"> var arr_province=[" ...

  6. 初学java之12 泛型编程的个人理解总结

    首先,强调一个观点: 对于我这样的初学者,一定要站在虚拟机和编译器的角度来分析java 语言的种种特性,泛型也不例外.(我认为这个一条正确的学习经验) 写这篇文章起源于最近在学java,有一天在路上和 ...

  7. 看看Maple T.A.的详细作用

    Maple T.A.是一个基于互联网的在线考试和智能评分系统,是Maplesoft公司 与美国数学协会(MAA)合作开发的成果,在全球拥有大量的院校用户.Maple T.A.提供了用户数据库.所见即所 ...

  8. Android内存清理

    直接上图吧! 获取文件大小 ,清理文件工具类 public class DataCleanManager { public static String getTotalCacheSize(Contex ...

  9. SQL Server差异备份的备份/还原原理

    SQL Server差异备份的备份/还原原理 记住一点:差异备份是基于最后一次完整备份的差异,而不是基于最后一次差异的差异   备份过程: 1-完整备份之后有无对数据库做过修改,如果有,记录数据库的最 ...

  10. 关于EF6的记录Sql语句 与 EntityFramework.Extend 的诟病

    1.关于EF6的记录Sql语句,一个老生长谈的问题. 他生成的sql语句实在是烂,大家都这样说 2.EF6 更新删除不方便,没有批量操作.所以,有人出了EF6.Extend  大家用起来也很爽 基于以 ...