YamlPropertiesFactoryBean consistently exposes String values

Issue: SPR-14737
This commit is contained in:
Juergen Hoeller
2016-09-25 21:05:40 +02:00
parent e188b4428e
commit 74c618892e
8 changed files with 147 additions and 104 deletions

View File

@@ -19,18 +19,21 @@ package org.springframework.beans.factory.config;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
/**
* Factory for a Map that reads from a YAML source. YAML is a nice human-readable
* format for configuration, and it has some useful hierarchical properties. It's
* more or less a superset of JSON, so it has a lot of similar features. If
* multiple resources are provided the later ones will override entries in the
* earlier ones hierarchically - that is all entries with the same nested key of
* type Map at any depth are merged. For example:
* Factory for a {@code Map} that reads from a YAML source, preserving the
* YAML-declared value types and their structure.
*
* <p>YAML is a nice human-readable format for configuration, and it has some
* useful hierarchical properties. It's more or less a superset of JSON, so it
* has a lot of similar features.
*
* <p>If multiple resources are provided the later ones will override entries in
* the earlier ones hierarchically; that is, all entries with the same nested key
* of type {@code Map} at any depth are merged. For example:
*
* <pre class="code">
* foo:
@@ -62,6 +65,7 @@ import org.springframework.beans.factory.InitializingBean;
* with the value in the second, but its nested values are merged.
*
* @author Dave Syer
* @author Juergen Hoeller
* @since 4.1
*/
public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean<Map<String, Object>>, InitializingBean {
@@ -112,13 +116,9 @@ public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean<Map
* @see #process(java.util.Map, MatchCallback)
*/
protected Map<String, Object> createMap() {
final Map<String, Object> result = new LinkedHashMap<>();
process(new MatchCallback() {
@Override
public void process(Properties properties, Map<String, Object> map) {
merge(result, map);
}
});
Map<String, Object> result = new LinkedHashMap<>();
process((properties, map) -> merge(result, map));
return result;
}

View File

@@ -37,6 +37,7 @@ import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.parser.ParserException;
import org.yaml.snakeyaml.reader.UnicodeReader;
import org.springframework.core.CollectionFactory;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -45,6 +46,7 @@ import org.springframework.util.StringUtils;
* Base class for YAML factories.
*
* @author Dave Syer
* @author Juergen Hoeller
* @since 4.1
*/
public abstract class YamlProcessor {
@@ -217,7 +219,7 @@ public abstract class YamlProcessor {
}
private boolean process(Map<String, Object> map, MatchCallback callback) {
Properties properties = new Properties();
Properties properties = CollectionFactory.createStringAdaptingProperties();
properties.putAll(getFlattenedMap(map));
if (this.documentMatchers.isEmpty()) {
@@ -302,21 +304,23 @@ public abstract class YamlProcessor {
}
}
else {
result.put(key, value != null ? value : "");
result.put(key, (value != null ? value : ""));
}
}
}
/**
* Callback interface used to process properties in a resulting map.
* Callback interface used to process the YAML parsing results.
*/
public interface MatchCallback {
/**
* Process the properties.
* @param properties the properties to process
* @param map a mutable result map
* Process the given representation of the parsing results.
* @param properties the properties to process (as a flattened
* representation with indexed keys in case of a collection or map)
* @param map the result map (preserving the original value structure
* in the YAML document)
*/
void process(Properties properties, Map<String, Object> map);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,18 +16,27 @@
package org.springframework.beans.factory.config;
import java.util.Map;
import java.util.Properties;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.CollectionFactory;
/**
* Factory for Java Properties that reads from a YAML source. YAML is a nice
* human-readable format for configuration, and it has some useful hierarchical
* properties. It's more or less a superset of JSON, so it has a lot of similar
* features. The Properties created by this factory have nested paths for
* hierarchical objects, so for instance this YAML
* Factory for {@link java.util.Properties} that reads from a YAML source,
* exposing a flat structure of String property values.
*
* <p>YAML is a nice human-readable format for configuration, and it has some
* useful hierarchical properties. It's more or less a superset of JSON, so it
* has a lot of similar features.
*
* <p><b>Note: All exposed values are of type {@code String}</b> for access through
* the common {@link Properties#getProperty} method (e.g. in configuration property
* resolution through {@link PropertyResourceConfigurer#setProperties(Properties)}).
* If this is not desirable, use {@link YamlMapFactoryBean} instead.
*
* <p>The Properties created by this factory have nested paths for hierarchical
* objects, so for instance this YAML
*
* <pre class="code">
* environments:
@@ -39,7 +48,7 @@ import org.springframework.beans.factory.InitializingBean;
* name: My Cool App
* </pre>
*
* is transformed into these Properties:
* is transformed into these properties:
*
* <pre class="code">
* environments.dev.url=http://dev.bar.com
@@ -57,7 +66,7 @@ import org.springframework.beans.factory.InitializingBean;
* - foo.bar.com
* </pre>
*
* becomes Java Properties like this:
* becomes properties like this:
*
* <pre class="code">
* servers[0]=dev.bar.com
@@ -66,6 +75,7 @@ import org.springframework.beans.factory.InitializingBean;
*
* @author Dave Syer
* @author Stephane Nicoll
* @author Juergen Hoeller
* @since 4.1
*/
public class YamlPropertiesFactoryBean extends YamlProcessor implements FactoryBean<Properties>, InitializingBean {
@@ -116,13 +126,8 @@ public class YamlPropertiesFactoryBean extends YamlProcessor implements FactoryB
* @see #process(MatchCallback) ()
*/
protected Properties createProperties() {
final Properties result = new Properties();
process(new MatchCallback() {
@Override
public void process(Properties properties, Map<String, Object> map) {
result.putAll(properties);
}
});
Properties result = CollectionFactory.createStringAdaptingProperties();
process((properties, map) -> result.putAll(properties));
return result;
}