原文地址: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. python 之 Django 小案例

    一, F  Q # F 使用查询条件的值 # # from django.db.models import F # models.Tb1.objects.update(num=F('num')+1) ...

  2. iOS开发之AFNetworking 3.0.4使用

    昨天使用Cocoapods导入AFN做POST的时候,导入的最新版的3.0.4,突然发现找不到AFHTTPRequestOperationManager了...上github上一看,发现没有这个了.刚 ...

  3. nodejs学习之events的使用

    实用events做个小例子: var mysql = require("mysql"); var Event = require("events").Event ...

  4. 使div下的图片自适应div的大小

    div img{ max-width:100%; height:auto; } 这里div 要给固定的宽度 开始这里还想了半天 用网上的方法也不行 问老大 又一句话就给我解决了...老大真男神啊!!! ...

  5. 如何使用Goolge Timeline工具

    网上中文的资料版本比较老,找到一个新版本的英文介绍,翻一下,原文:https://developers.google.com/web/tools/chrome-devtools/profile/eva ...

  6. HTML以及CSS的作用和理念

    首先,在学习之前,这些是必要知道的东西.什么是HTML,什么是CSS 它们有什么用?又能做什么? 了解HTML和CSS的用途,能更有利我们快速,高效的学习它们. 那么,关于这两者,我就用我通俗的语言像 ...

  7. UITableView(一)

    #import <UIKit/UIKit.h> @interface ViewController : UIViewController<UITableViewDataSource, ...

  8. java中文乱码解决之道(八)-----解决URL中文乱码问题

    我们主要通过两种形式提交向服务器发送请求:URL.表单.而表单形式一般都不会出现乱码问题,乱码问题主要是在URL上面.通过前面几篇博客的介绍我们知道URL向服务器发送请求编码过程实在是实在太混乱了.不 ...

  9. 在C#代码中应用Log4Net(三)Log4Net中配置文件的解释

    一个完整的配置文件的例子如下所示,这个是”在C#代码中应用Log4Net(二)”中使用的配置文件. <log4net> <!-- 错误日志类--> <logger nam ...

  10. Webstorm 10 for mac osx 注册机,序列号,kegen

    小菜最近get到mac体验机会,早就耳闻mac非常适合做开发,于是迫不及待的安装各种开发工具,不知不觉,轮到前端开发神器webstorm了,看了一下官网的价格,心拔凉拔凉的. 果断搜索注册机,搜到的结 ...