context:property-placeholder

spring 的context:property-placeholder

在集成spring的时候,报了这么个错误

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'jdbc.driverClassName' in string value "${jdbc.driverClassName}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:204)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:178)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:172)
at org.springframework.beans.factory.config.BeanDefinitionVisitor.resolveStringValue(BeanDefinitionVisitor.java:282)
at org.springframework.beans.factory.config.BeanDefinitionVisitor.resolveValue(BeanDefinitionVisitor.java:204)
at org.springframework.beans.factory.config.BeanDefinitionVisitor.visitPropertyValues(BeanDefinitionVisitor.java:141)
at org.springframework.beans.factory.config.BeanDefinitionVisitor.visitBeanDefinition(BeanDefinitionVisitor.java:82)
at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:208)
... 18 more

发现${jdbc.driverClassName}没有解析,查了一下配置文件,发现我配置了两个 <context:property-placeholder location="xxxx"/> 之前只有一个时候是正常的,后面加了一个出现这
错误了,这个是什么原因呢?

分析context:property-placeholder/ 这个标签,我注册了两个这个标签,则会注册两个PropertySourcesPlaceholderConfigurer bean,这个bean,其实质是个BeanPostProcessor,
而location里面的配置文件最后会被解析到propertySources这个属性里面,故每个PropertySourcesPlaceholderConfigurer执行解析${}的时候,只会匹配自己的propertySources
而后在其解析这些${xxx}的时候,调用到PropertyPlaceholderHelper的parseStringValue()的方法时候,

protected String parseStringValue(
		String strVal, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {

	StringBuilder result = new StringBuilder(strVal);

	int startIndex = strVal.indexOf(this.placeholderPrefix);
	while (startIndex != -1) {
		int endIndex = findPlaceholderEndIndex(result, startIndex);
		if (endIndex != -1) {
			String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
			String originalPlaceholder = placeholder;
			if (!visitedPlaceholders.add(originalPlaceholder)) {
				throw new IllegalArgumentException(
						"Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
			}
			// Recursive invocation, parsing placeholders contained in the placeholder key.
			placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
			// Now obtain the value for the fully resolved key...
			String propVal = placeholderResolver.resolvePlaceholder(placeholder);
			if (propVal == null && this.valueSeparator != null) {
				int separatorIndex = placeholder.indexOf(this.valueSeparator);
				if (separatorIndex != -1) {
					String actualPlaceholder = placeholder.substring(0, separatorIndex);
					String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
					propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
					if (propVal == null) {
						propVal = defaultValue;
					}
				}
			}
			解析出来了
			if (propVal != null) {
				// Recursive invocation, parsing placeholders contained in the
				// previously resolved placeholder value.
				propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
				result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
				if (logger.isTraceEnabled()) {
					logger.trace("Resolved placeholder '" + placeholder + "'");
				}
				startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
			}
			没有
			else if (this.ignoreUnresolvablePlaceholders) {
				// Proceed with unprocessed value.
				startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
			}
			else {
				throw new IllegalArgumentException("Could not resolve placeholder '" +
						placeholder + "'" + " in string value \"" + strVal + "\"");
			}
			visitedPlaceholders.remove(originalPlaceholder);
		}
		else {
			startIndex = -1;
		}
	}

	return result.toString();
}

可以看到ignoreUnresolvablePlaceholders在这个值为false的时候,其会抛出异常,所有这个的解决办法是 在

<context:property-placeholder ignore-unresolvable="true" location="classpath:xx.properties" /> 

将ignore-unresolvable设置为true,但是这样做有个弊端,若xml里面写的真是没有的话?则不会抛出异常,这样不好

想到这种BeanPostProccor 一般会实现 Ordered 这个接口 所以我们可以设置他们的调用顺序,在最后的那个context:property-placeholder标签不设置ignore-unresolvable

如下

<context:property-placeholder order="1" ignore-unresolvable="true" location="classpath:a.properties" /> 


<context:property-placeholder order="2" ignore-unresolvable="false"  location="classpath:b.properties" /> 

这样也挺麻烦的,,所有还是把这些都放在一个标签里面写吧

posted on 2016-03-30 17:09  liaozq  阅读(1227)  评论(0编辑  收藏  举报