Commit 1a85e629 authored by Phillip Webb's avatar Phillip Webb

Stop using streams when working with sources

Replace `streamSources()` calls with `getSources()` in an attempt to
reduce the amount of garbage created.

Closes gh-13565
parent 9e7478a1
...@@ -34,6 +34,7 @@ import org.springframework.boot.context.event.ApplicationPreparedEvent; ...@@ -34,6 +34,7 @@ import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.context.event.ApplicationStartingEvent; import org.springframework.boot.context.event.ApplicationStartingEvent;
import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.logging.LogFile; import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggingInitializationContext; import org.springframework.boot.logging.LoggingInitializationContext;
...@@ -88,6 +89,12 @@ import org.springframework.util.StringUtils; ...@@ -88,6 +89,12 @@ import org.springframework.util.StringUtils;
*/ */
public class LoggingApplicationListener implements GenericApplicationListener { public class LoggingApplicationListener implements GenericApplicationListener {
private static final ConfigurationPropertyName LOGGING_LEVEL = ConfigurationPropertyName
.of("logging.level");
private static final ConfigurationPropertyName LOGGING_GROUP = ConfigurationPropertyName
.of("logging.group");
private static final Bindable<Map<String, String>> STRING_STRING_MAP = Bindable private static final Bindable<Map<String, String>> STRING_STRING_MAP = Bindable
.mapOf(String.class, String.class); .mapOf(String.class, String.class);
...@@ -324,8 +331,8 @@ public class LoggingApplicationListener implements GenericApplicationListener { ...@@ -324,8 +331,8 @@ public class LoggingApplicationListener implements GenericApplicationListener {
} }
Binder binder = Binder.get(environment); Binder binder = Binder.get(environment);
Map<String, String[]> groups = getGroups(); Map<String, String[]> groups = getGroups();
binder.bind("logging.group", STRING_STRINGS_MAP.withExistingValue(groups)); binder.bind(LOGGING_GROUP, STRING_STRINGS_MAP.withExistingValue(groups));
Map<String, String> levels = binder.bind("logging.level", STRING_STRING_MAP) Map<String, String> levels = binder.bind(LOGGING_LEVEL, STRING_STRING_MAP)
.orElseGet(Collections::emptyMap); .orElseGet(Collections::emptyMap);
levels.forEach((name, level) -> { levels.forEach((name, level) -> {
String[] groupedNames = groups.get(name); String[] groupedNames = groups.get(name);
......
...@@ -30,7 +30,6 @@ import java.util.Set; ...@@ -30,7 +30,6 @@ import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.springframework.beans.PropertyEditorRegistry; import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
...@@ -254,7 +253,7 @@ public class Binder { ...@@ -254,7 +253,7 @@ public class Binder {
private <T> Object bindObject(ConfigurationPropertyName name, Bindable<T> target, private <T> Object bindObject(ConfigurationPropertyName name, Bindable<T> target,
BindHandler handler, Context context, boolean allowRecursiveBinding) { BindHandler handler, Context context, boolean allowRecursiveBinding) {
ConfigurationProperty property = findProperty(name, context); ConfigurationProperty property = findProperty(name, context);
if (property == null && containsNoDescendantOf(context.streamSources(), name)) { if (property == null && containsNoDescendantOf(context.getSources(), name)) {
return null; return null;
} }
AggregateBinder<?> aggregateBinder = getAggregateBinder(target, context); AggregateBinder<?> aggregateBinder = getAggregateBinder(target, context);
...@@ -310,9 +309,13 @@ public class Binder { ...@@ -310,9 +309,13 @@ public class Binder {
if (name.isEmpty()) { if (name.isEmpty()) {
return null; return null;
} }
return context.streamSources() for (ConfigurationPropertySource source : context.getSources()) {
.map((source) -> source.getConfigurationProperty(name)) ConfigurationProperty property = source.getConfigurationProperty(name);
.filter(Objects::nonNull).findFirst().orElse(null); if (property != null) {
return property;
}
}
return null;
} }
private <T> Object bindProperty(Bindable<T> target, Context context, private <T> Object bindProperty(Bindable<T> target, Context context,
...@@ -326,7 +329,7 @@ public class Binder { ...@@ -326,7 +329,7 @@ public class Binder {
private Object bindBean(ConfigurationPropertyName name, Bindable<?> target, private Object bindBean(ConfigurationPropertyName name, Bindable<?> target,
BindHandler handler, Context context, boolean allowRecursiveBinding) { BindHandler handler, Context context, boolean allowRecursiveBinding) {
if (containsNoDescendantOf(context.streamSources(), name) if (containsNoDescendantOf(context.getSources(), name)
|| isUnbindableBean(name, target, context)) { || isUnbindableBean(name, target, context)) {
return null; return null;
} }
...@@ -345,10 +348,11 @@ public class Binder { ...@@ -345,10 +348,11 @@ public class Binder {
private boolean isUnbindableBean(ConfigurationPropertyName name, Bindable<?> target, private boolean isUnbindableBean(ConfigurationPropertyName name, Bindable<?> target,
Context context) { Context context) {
if (context.streamSources().anyMatch((s) -> s for (ConfigurationPropertySource source : context.getSources()) {
.containsDescendantOf(name) == ConfigurationPropertyState.PRESENT)) { if (source.containsDescendantOf(name) == ConfigurationPropertyState.PRESENT) {
// We know there are properties to bind so we can't bypass anything // We know there are properties to bind so we can't bypass anything
return false; return false;
}
} }
Class<?> resolved = target.getType().resolve(Object.class); Class<?> resolved = target.getType().resolve(Object.class);
if (resolved.isPrimitive() || NON_BEAN_CLASSES.contains(resolved)) { if (resolved.isPrimitive() || NON_BEAN_CLASSES.contains(resolved)) {
...@@ -357,10 +361,14 @@ public class Binder { ...@@ -357,10 +361,14 @@ public class Binder {
return resolved.getName().startsWith("java."); return resolved.getName().startsWith("java.");
} }
private boolean containsNoDescendantOf(Stream<ConfigurationPropertySource> sources, private boolean containsNoDescendantOf(Iterable<ConfigurationPropertySource> sources,
ConfigurationPropertyName name) { ConfigurationPropertyName name) {
return sources.allMatch( for (ConfigurationPropertySource source : sources) {
(s) -> s.containsDescendantOf(name) == ConfigurationPropertyState.ABSENT); if (source.containsDescendantOf(name) != ConfigurationPropertyState.ABSENT) {
return false;
}
}
return true;
} }
/** /**
...@@ -453,13 +461,6 @@ public class Binder { ...@@ -453,13 +461,6 @@ public class Binder {
this.configurationProperty = null; this.configurationProperty = null;
} }
public Stream<ConfigurationPropertySource> streamSources() {
if (this.sourcePushCount > 0) {
return this.source.stream();
}
return StreamSupport.stream(Binder.this.sources.spliterator(), false);
}
public PlaceholdersResolver getPlaceholdersResolver() { public PlaceholdersResolver getPlaceholdersResolver() {
return Binder.this.placeholdersResolver; return Binder.this.placeholdersResolver;
} }
......
...@@ -29,6 +29,7 @@ import java.util.function.Supplier; ...@@ -29,6 +29,7 @@ import java.util.function.Supplier;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.boot.context.properties.bind.Binder.Context; import org.springframework.boot.context.properties.bind.Binder.Context;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName; import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.ConfigurationPropertyState; import org.springframework.boot.context.properties.source.ConfigurationPropertyState;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
...@@ -44,8 +45,7 @@ class JavaBeanBinder implements BeanBinder { ...@@ -44,8 +45,7 @@ class JavaBeanBinder implements BeanBinder {
@Override @Override
public <T> T bind(ConfigurationPropertyName name, Bindable<T> target, Context context, public <T> T bind(ConfigurationPropertyName name, Bindable<T> target, Context context,
BeanPropertyBinder propertyBinder) { BeanPropertyBinder propertyBinder) {
boolean hasKnownBindableProperties = context.streamSources().anyMatch(( boolean hasKnownBindableProperties = hasKnownBindableProperties(name, context);
s) -> s.containsDescendantOf(name) == ConfigurationPropertyState.PRESENT);
Bean<T> bean = Bean.get(target, hasKnownBindableProperties); Bean<T> bean = Bean.get(target, hasKnownBindableProperties);
if (bean == null) { if (bean == null) {
return null; return null;
...@@ -55,6 +55,16 @@ class JavaBeanBinder implements BeanBinder { ...@@ -55,6 +55,16 @@ class JavaBeanBinder implements BeanBinder {
return (bound ? beanSupplier.get() : null); return (bound ? beanSupplier.get() : null);
} }
private boolean hasKnownBindableProperties(ConfigurationPropertyName name,
Context context) {
for (ConfigurationPropertySource source : context.getSources()) {
if (source.containsDescendantOf(name) == ConfigurationPropertyState.PRESENT) {
return true;
}
}
return false;
}
private <T> boolean bind(BeanPropertyBinder propertyBinder, Bean<T> bean, private <T> boolean bind(BeanPropertyBinder propertyBinder, Bean<T> bean,
BeanSupplier<T> beanSupplier) { BeanSupplier<T> beanSupplier) {
boolean bound = false; boolean bound = false;
......
...@@ -57,8 +57,7 @@ class MapBinder extends AggregateBinder<Map<Object, Object>> { ...@@ -57,8 +57,7 @@ class MapBinder extends AggregateBinder<Map<Object, Object>> {
Map<Object, Object> map = CollectionFactory.createMap((target.getValue() != null) Map<Object, Object> map = CollectionFactory.createMap((target.getValue() != null)
? Map.class : target.getType().resolve(Object.class), 0); ? Map.class : target.getType().resolve(Object.class), 0);
Bindable<?> resolvedTarget = resolveTarget(target); Bindable<?> resolvedTarget = resolveTarget(target);
boolean hasDescendants = getContext().streamSources().anyMatch((source) -> source boolean hasDescendants = hasDescendants(name);
.containsDescendantOf(name) == ConfigurationPropertyState.PRESENT);
for (ConfigurationPropertySource source : getContext().getSources()) { for (ConfigurationPropertySource source : getContext().getSources()) {
if (!ConfigurationPropertyName.EMPTY.equals(name)) { if (!ConfigurationPropertyName.EMPTY.equals(name)) {
ConfigurationProperty property = source.getConfigurationProperty(name); ConfigurationProperty property = source.getConfigurationProperty(name);
...@@ -73,6 +72,15 @@ class MapBinder extends AggregateBinder<Map<Object, Object>> { ...@@ -73,6 +72,15 @@ class MapBinder extends AggregateBinder<Map<Object, Object>> {
return map.isEmpty() ? null : map; return map.isEmpty() ? null : map;
} }
private boolean hasDescendants(ConfigurationPropertyName name) {
for (ConfigurationPropertySource source : getContext().getSources()) {
if (source.containsDescendantOf(name) == ConfigurationPropertyState.PRESENT) {
return true;
}
}
return false;
}
private Bindable<?> resolveTarget(Bindable<?> target) { private Bindable<?> resolveTarget(Bindable<?> target) {
Class<?> type = target.getType().resolve(Object.class); Class<?> type = target.getType().resolve(Object.class);
if (Properties.class.isAssignableFrom(type)) { if (Properties.class.isAssignableFrom(type)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment