Shared DefaultConversionService instance for simple fallback purposes
Issue: SPR-14948
(cherry picked from commit 80931b2)
This commit is contained in:
@@ -52,6 +52,30 @@ public class DefaultConversionService extends GenericConversionService {
|
||||
private static final boolean streamAvailable = ClassUtils.isPresent(
|
||||
"java.util.stream.Stream", DefaultConversionService.class.getClassLoader());
|
||||
|
||||
private static volatile DefaultConversionService sharedInstance;
|
||||
|
||||
|
||||
/**
|
||||
* Return a shared default {@code ConversionService} instance,
|
||||
* lazily building it once needed.
|
||||
* <p><b>NOTE:</b> We highly recommend constructing individual
|
||||
* {@code ConversionService} instances for customization purposes.
|
||||
* This accessor is only meant as a fallback for code paths which
|
||||
* need simple type coercion but cannot access a longer-lived
|
||||
* {@code ConversionService} instance any other way.
|
||||
* @return the shared {@code ConversionService} instance (never {@code null})
|
||||
* @since 4.3.5
|
||||
*/
|
||||
public static ConversionService getSharedInstance() {
|
||||
if (sharedInstance == null) {
|
||||
synchronized (DefaultConversionService.class) {
|
||||
if (sharedInstance == null) {
|
||||
sharedInstance = new DefaultConversionService();
|
||||
}
|
||||
}
|
||||
}
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,8 +22,11 @@ import java.util.Set;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.PropertyPlaceholderHelper;
|
||||
import org.springframework.util.SystemPropertyUtils;
|
||||
|
||||
@@ -38,7 +41,7 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected ConfigurableConversionService conversionService = new DefaultConversionService();
|
||||
private volatile ConfigurableConversionService conversionService;
|
||||
|
||||
private PropertyPlaceholderHelper nonStrictHelper;
|
||||
|
||||
@@ -57,11 +60,21 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
|
||||
|
||||
@Override
|
||||
public ConfigurableConversionService getConversionService() {
|
||||
return this.conversionService;
|
||||
// Need to provide an independent DefaultConversionService, not the
|
||||
// shared DefaultConversionService used by PropertySourcesPropertyResolver.
|
||||
if (this.conversionService == null) {
|
||||
synchronized (this) {
|
||||
if (this.conversionService == null) {
|
||||
this.conversionService = new DefaultConversionService();
|
||||
}
|
||||
}
|
||||
}
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConversionService(ConfigurableConversionService conversionService) {
|
||||
Assert.notNull(conversionService, "ConversionService must not be null");
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
@@ -72,6 +85,7 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
|
||||
*/
|
||||
@Override
|
||||
public void setPlaceholderPrefix(String placeholderPrefix) {
|
||||
Assert.notNull(placeholderPrefix, "'placeholderPrefix' must not be null");
|
||||
this.placeholderPrefix = placeholderPrefix;
|
||||
}
|
||||
|
||||
@@ -82,6 +96,7 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
|
||||
*/
|
||||
@Override
|
||||
public void setPlaceholderSuffix(String placeholderSuffix) {
|
||||
Assert.notNull(placeholderSuffix, "'placeholderSuffix' must not be null");
|
||||
this.placeholderSuffix = placeholderSuffix;
|
||||
}
|
||||
|
||||
@@ -113,8 +128,10 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
|
||||
|
||||
@Override
|
||||
public void setRequiredProperties(String... requiredProperties) {
|
||||
for (String key : requiredProperties) {
|
||||
this.requiredProperties.add(key);
|
||||
if (requiredProperties != null) {
|
||||
for (String key : requiredProperties) {
|
||||
this.requiredProperties.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +241,31 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given value to the specified target type, if necessary.
|
||||
* @param value the original property value
|
||||
* @param targetType the specified target type for property retrieval
|
||||
* @return the converted value, or the original value if no conversion
|
||||
* is necessary
|
||||
* @since 4.3.5
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T convertValueIfNecessary(Object value, Class<T> targetType) {
|
||||
if (targetType == null) {
|
||||
return (T) value;
|
||||
}
|
||||
ConversionService csToUse = this.conversionService;
|
||||
if (csToUse == null) {
|
||||
// Avoid initialization of shared DefaultConversionService if
|
||||
// no standard type conversion is needed in the first place...
|
||||
if (ClassUtils.isAssignableValue(targetType, value)) {
|
||||
return (T) value;
|
||||
}
|
||||
csToUse = DefaultConversionService.getSharedInstance();
|
||||
}
|
||||
return csToUse.convert(value, targetType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the specified property as a raw String,
|
||||
|
||||
@@ -83,7 +83,7 @@ public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
|
||||
value = resolveNestedPlaceholders((String) value);
|
||||
}
|
||||
logKeyFound(key, propertySource, value);
|
||||
return this.conversionService.convert(value, targetValueType);
|
||||
return convertValueIfNecessary(value, targetValueType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user