package com.dianping.puma.common.spring; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.util.Assert; import java.util.ArrayList; import java.util.List; import java.util.Properties; /** * 扩展Spring的{@linkplain org.springframework.beans.factory.config.PropertyPlaceholderConfigurer} ,增加默认值的功能。 * 例如:${placeholder:defaultValue},假如placeholder的值不存在,则默认取得 defaultValue。 * * @author jianghang 2013-1-24 下午03:37:56 * @version 1.0.0 */ public class PropertyPlaceholderConfigurer extends org.springframework.beans.factory.config.PropertyPlaceholderConfigurer implements ResourceLoaderAware, InitializingBean { private static final String PLACEHOLDER_PREFIX = "${"; private static final String PLACEHOLDER_SUFFIX = "}"; private ResourceLoader loader; private String[] locationNames; public PropertyPlaceholderConfigurer(){ setIgnoreUnresolvablePlaceholders(true); } public void setResourceLoader(ResourceLoader loader) { this.loader = loader; } public void setLocationNames(String[] locations) { this.locationNames = locations; } public void afterPropertiesSet() throws Exception { Assert.notNull(loader, "no resourceLoader"); if (locationNames != null) { for (int i = 0; i < locationNames.length; i++) { locationNames[i] = resolveSystemPropertyPlaceholders(locationNames[i]); } } if (locationNames != null) { List<Resource> resources = new ArrayList<Resource>(locationNames.length); for (String location : locationNames) { location = trimToNull(location); if (location != null) { resources.add(loader.getResource(location)); } } super.setLocations(resources.toArray(new Resource[resources.size()])); } } private String resolveSystemPropertyPlaceholders(String text) { StringBuilder buf = new StringBuilder(text); for (int startIndex = buf.indexOf(PLACEHOLDER_PREFIX); startIndex >= 0;) { int endIndex = buf.indexOf(PLACEHOLDER_SUFFIX, startIndex + PLACEHOLDER_PREFIX.length()); if (endIndex != -1) { String placeholder = buf.substring(startIndex + PLACEHOLDER_PREFIX.length(), endIndex); int nextIndex = endIndex + PLACEHOLDER_SUFFIX.length(); try { String value = resolveSystemPropertyPlaceholder(placeholder); if (value != null) { buf.replace(startIndex, endIndex + PLACEHOLDER_SUFFIX.length(), value); nextIndex = startIndex + value.length(); } else { System.err.println("Could not resolve placeholder '" + placeholder + "' in [" + text + "] as system property: neither system property nor environment variable found"); } } catch (Throwable ex) { System.err.println("Could not resolve placeholder '" + placeholder + "' in [" + text + "] as system property: " + ex); } startIndex = buf.indexOf(PLACEHOLDER_PREFIX, nextIndex); } else { startIndex = -1; } } return buf.toString(); } private String resolveSystemPropertyPlaceholder(String placeholder) { DefaultablePlaceholder dp = new DefaultablePlaceholder(placeholder); String value = System.getProperty(dp.placeholder); if (value == null) { value = System.getenv(dp.placeholder); } if (value == null) { value = dp.defaultValue; } return value; } @Override protected String resolvePlaceholder(String placeholder, Properties props, int systemPropertiesMode) { DefaultablePlaceholder dp = new DefaultablePlaceholder(placeholder); String value = super.resolvePlaceholder(dp.placeholder, props, systemPropertiesMode); if (value == null) { value = dp.defaultValue; } return trimToEmpty(value); } private static class DefaultablePlaceholder { private final String defaultValue; private final String placeholder; public DefaultablePlaceholder(String placeholder){ int commaIndex = placeholder.indexOf(":"); String defaultValue = null; if (commaIndex >= 0) { defaultValue = trimToEmpty(placeholder.substring(commaIndex + 1)); placeholder = trimToEmpty(placeholder.substring(0, commaIndex)); } this.placeholder = placeholder; this.defaultValue = defaultValue; } } private String trimToNull(String str) { if (str == null) { return null; } String result = str.trim(); if (result == null || result.length() == 0) { return null; } return result; } public static String trimToEmpty(String str) { if (str == null) { return ""; } return str.trim(); } }