Introduce PropertyResolver#getPropertyAsClass
This commit is contained in:
parent
275d43dfde
commit
4b5208faad
|
|
@ -196,6 +196,10 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
|
||||||
return this.propertyResolver.getProperty(key, targetType);
|
return this.propertyResolver.getProperty(key, targetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <T> Class<T> getPropertyAsClass(String key, Class<T> targetType) {
|
||||||
|
return this.propertyResolver.getPropertyAsClass(key, targetType);
|
||||||
|
}
|
||||||
|
|
||||||
public String getRequiredProperty(String key) throws IllegalStateException {
|
public String getRequiredProperty(String key) throws IllegalStateException {
|
||||||
return this.propertyResolver.getRequiredProperty(key);
|
return this.propertyResolver.getRequiredProperty(key);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,15 @@ public interface PropertyResolver {
|
||||||
*/
|
*/
|
||||||
<T> T getProperty(String key, Class<T> targetType);
|
<T> T getProperty(String key, Class<T> targetType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the property value associated with the given key to a {@code Class}
|
||||||
|
* of type {@code T} or {@code null} if the key cannot be resolved.
|
||||||
|
* @throws ConversionException if class specified by property value cannot be found
|
||||||
|
* or loaded or if targetType is not assignable from class specified by property value
|
||||||
|
* @see #getProperty(String, Class)
|
||||||
|
*/
|
||||||
|
<T> Class<T> getPropertyAsClass(String key, Class<T> targetType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the property value associated with the given key, converted to the given
|
* Return the property value associated with the given key, converted to the given
|
||||||
* targetType (never {@code null}).
|
* targetType (never {@code null}).
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ package org.springframework.core.env;
|
||||||
|
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.ConversionException;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link PropertyResolver} implementation that resolves property values against
|
* {@link PropertyResolver} implementation that resolves property values against
|
||||||
* an underlying set of {@link PropertySources}.
|
* an underlying set of {@link PropertySources}.
|
||||||
|
|
@ -58,7 +61,7 @@ public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace(format("getProperty(\"%s\", %s)", key, targetValueType.getSimpleName()));
|
logger.trace(format("getProperty(\"%s\", %s)", key, targetValueType.getSimpleName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PropertySource<?> propertySource : this.propertySources) {
|
for (PropertySource<?> propertySource : this.propertySources) {
|
||||||
if (debugEnabled) {
|
if (debugEnabled) {
|
||||||
logger.debug(format("Searching for key '%s' in [%s]", key, propertySource.getName()));
|
logger.debug(format("Searching for key '%s' in [%s]", key, propertySource.getName()));
|
||||||
|
|
@ -79,11 +82,68 @@ public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
|
||||||
return conversionService.convert(value, targetValueType);
|
return conversionService.convert(value, targetValueType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debugEnabled) {
|
if (debugEnabled) {
|
||||||
logger.debug(format("Could not find key '%s' in any property source. Returning [null]", key));
|
logger.debug(format("Could not find key '%s' in any property source. Returning [null]", key));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <T> Class<T> getPropertyAsClass(String key, Class<T> targetValueType) {
|
||||||
|
boolean debugEnabled = logger.isDebugEnabled();
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace(format("getPropertyAsClass(\"%s\", %s)", key, targetValueType.getSimpleName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PropertySource<?> propertySource : this.propertySources) {
|
||||||
|
if (debugEnabled) {
|
||||||
|
logger.debug(format("Searching for key '%s' in [%s]", key, propertySource.getName()));
|
||||||
|
}
|
||||||
|
Object value;
|
||||||
|
if ((value = propertySource.getProperty(key)) != null) {
|
||||||
|
if (debugEnabled) {
|
||||||
|
logger.debug(
|
||||||
|
format("Found key '%s' in [%s] with value '%s'", key, propertySource.getName(), value));
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<?> clazz;
|
||||||
|
if (value instanceof String) {
|
||||||
|
try {
|
||||||
|
clazz = ClassUtils.forName((String)value, null);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new ClassConversionException((String)value, targetValueType, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (value instanceof Class) {
|
||||||
|
clazz = (Class<?>)value;
|
||||||
|
} else {
|
||||||
|
clazz = value.getClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!targetValueType.isAssignableFrom(clazz)) {
|
||||||
|
throw new ClassConversionException(clazz, targetValueType);
|
||||||
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Class<T> targetClass = (Class<T>)clazz;
|
||||||
|
return targetClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debugEnabled) {
|
||||||
|
logger.debug(format("Could not find key '%s' in any property source. Returning [null]", key));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
static class ClassConversionException extends ConversionException {
|
||||||
|
public ClassConversionException(Class<?> actual, Class<?> expected) {
|
||||||
|
super(String.format("Actual type %s is not assignable to expected type %s", actual.getName(), expected.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassConversionException(String actual, Class<?> expected, Exception ex) {
|
||||||
|
super(String.format("Could not find/load class %s during attempt to convert to %s", actual, expected.getName()), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import static org.hamcrest.CoreMatchers.nullValue;
|
import static org.hamcrest.CoreMatchers.nullValue;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -28,6 +29,7 @@ import java.util.Properties;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.springframework.core.convert.ConversionException;
|
||||||
import org.springframework.mock.env.MockPropertySource;
|
import org.springframework.mock.env.MockPropertySource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -238,4 +240,70 @@ public class PropertySourcesPropertyResolverTests {
|
||||||
new PropertySourcesPropertyResolver(new MutablePropertySources()).resolveRequiredPlaceholders(null);
|
new PropertySourcesPropertyResolver(new MutablePropertySources()).resolveRequiredPlaceholders(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getPropertyAsClass() throws ClassNotFoundException, LinkageError {
|
||||||
|
MutablePropertySources propertySources = new MutablePropertySources();
|
||||||
|
propertySources.addFirst(new MockPropertySource().withProperty("some.class", SpecificType.class.getName()));
|
||||||
|
PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
|
||||||
|
assertTrue(resolver.getPropertyAsClass("some.class", SomeType.class).equals(SpecificType.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getPropertyAsClass_withInterfaceAsTarget() throws ClassNotFoundException, LinkageError {
|
||||||
|
MutablePropertySources propertySources = new MutablePropertySources();
|
||||||
|
propertySources.addFirst(new MockPropertySource().withProperty("some.class", SomeType.class.getName()));
|
||||||
|
PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
|
||||||
|
assertTrue(resolver.getPropertyAsClass("some.class", SomeType.class).equals(SomeType.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=ConversionException.class)
|
||||||
|
public void getPropertyAsClass_withMismatchedTypeForValue() {
|
||||||
|
MutablePropertySources propertySources = new MutablePropertySources();
|
||||||
|
propertySources.addFirst(new MockPropertySource().withProperty("some.class", "java.lang.String"));
|
||||||
|
PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
|
||||||
|
resolver.getPropertyAsClass("some.class", SomeType.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=ConversionException.class)
|
||||||
|
public void getPropertyAsClass_withNonExistentClassForValue() {
|
||||||
|
MutablePropertySources propertySources = new MutablePropertySources();
|
||||||
|
propertySources.addFirst(new MockPropertySource().withProperty("some.class", "some.bogus.Class"));
|
||||||
|
PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
|
||||||
|
resolver.getPropertyAsClass("some.class", SomeType.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getPropertyAsClass_withObjectForValue() {
|
||||||
|
MutablePropertySources propertySources = new MutablePropertySources();
|
||||||
|
propertySources.addFirst(new MockPropertySource().withProperty("some.class", new SpecificType()));
|
||||||
|
PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
|
||||||
|
assertTrue(resolver.getPropertyAsClass("some.class", SomeType.class).equals(SpecificType.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=ConversionException.class)
|
||||||
|
public void getPropertyAsClass_withMismatchedObjectForValue() {
|
||||||
|
MutablePropertySources propertySources = new MutablePropertySources();
|
||||||
|
propertySources.addFirst(new MockPropertySource().withProperty("some.class", new Integer(42)));
|
||||||
|
PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
|
||||||
|
resolver.getPropertyAsClass("some.class", SomeType.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getPropertyAsClass_withRealClassForValue() {
|
||||||
|
MutablePropertySources propertySources = new MutablePropertySources();
|
||||||
|
propertySources.addFirst(new MockPropertySource().withProperty("some.class", SpecificType.class));
|
||||||
|
PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
|
||||||
|
assertTrue(resolver.getPropertyAsClass("some.class", SomeType.class).equals(SpecificType.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=ConversionException.class)
|
||||||
|
public void getPropertyAsClass_withMismatchedRealClassForValue() {
|
||||||
|
MutablePropertySources propertySources = new MutablePropertySources();
|
||||||
|
propertySources.addFirst(new MockPropertySource().withProperty("some.class", Integer.class));
|
||||||
|
PropertyResolver resolver = new PropertySourcesPropertyResolver(propertySources);
|
||||||
|
resolver.getPropertyAsClass("some.class", SomeType.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
static interface SomeType { }
|
||||||
|
static class SpecificType implements SomeType { }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue