在Spring项目中,我们常常会使用·PropertyPlaceholderConfigurer·来做一些配置宏替换,例如,XML中配置jdbc时会采用${jdbc.masterUsername}
这种形式,在Spring加载时会将${jdbc.masterUsername}
替换为property文件中键jdbc.masterUsername
对应的值。
但是PropertyPlaceholderConfigurer
只支持property文件,而实际应用中可能不止有property文件,或许会用到其他的配置文件,例如com.typesafe.config
支持的conf文件配置。因此可以对PropertyPlaceholderConfigurer
做如下扩展:
public class MyPropertyPlaceholder extends PropertyPlaceholderConfigurer {
private static final Logger LOGGER = LoggerFactory.getLogger(MyPropertyPlaceholder.class);
private Resource conf;
private Config config;
@Override
protected String resolvePlaceholder(String placeholder, Properties props) {
String propVal = super.resolvePlaceholder(placeholder, props);
if (propVal == null) {
propVal = config.getString(placeholder);
}
return propVal;
}
@Override
protected void loadProperties(Properties props) throws IOException {
super.loadProperties(props);
try {
config = ConfigFactory.parseFile(conf.getFile());
LOGGER.info("Loading conf file from " + conf);
} catch (Exception e) {
e.printStackTrace();
}
}
public void setConf(Resource conf) {
this.conf = conf;
}
}
PropertyPlaceholderConfigurer
原理是通过BeanFactoryPostProcessor
来实现对所有的beanDefinition的property中的${xxx}
,替换为property文件的xxx
键对应的值。
因此扩展的时候,继承PropertyPlaceholderConfigurer
,保留PropertyPlaceholderConfigurer
之前的location
等属性注入property文件,但是扩展了需要的conf文件。重写loadProperties()
方法,不仅加载property文件,还加载需要的conf文件。重写resolvePlaceholder()
方法,先在Properties去找对应的placeholder(即xxx
),如果没有值,则去conf文件中去找键xxx
对应值。
在XML中移除PropertyPlaceholderConfigurer
的Bean,而使用MyPropertyPlaceholder
:
<bean id="propertyConf" class="xxx.xxx.xxx.MyPropertyPlaceholder">
<property name="location" value="test.properties"/>
<property name="conf" value="test.conf"/>
</bean>
MyPropertyPlaceholder
不仅可以用来做配置宏替换,还可以作为配置参数的获取,只需要用static属性保存住配置值,对外提供static方法来获取即可。