EntryBinder Class — spring-boot Architecture
Architecture documentation for the EntryBinder class in MapBinder.java from the spring-boot codebase.
Entity Profile
Relationship Graph
Source Code
core/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java lines 148–246
private class EntryBinder {
private final ConfigurationPropertyName root;
private final AggregateElementBinder elementBinder;
private final ResolvableType mapType;
private final ResolvableType keyType;
private final ResolvableType valueType;
private final Class<?> resolvedValueType;
private final boolean valueTreatedAsNestedMap;
private final Bindable<Object> bindableMapType;
private final Bindable<Object> bindableValueType;
EntryBinder(ConfigurationPropertyName root, Bindable<?> target, AggregateElementBinder elementBinder) {
this.root = root;
this.elementBinder = elementBinder;
this.mapType = target.getType().asMap();
this.keyType = this.mapType.getGeneric(0);
this.valueType = this.mapType.getGeneric(1);
this.resolvedValueType = this.valueType.resolve(Object.class);
this.valueTreatedAsNestedMap = Object.class.equals(this.resolvedValueType);
this.bindableMapType = Bindable.of(this.mapType);
this.bindableValueType = Bindable.of(this.valueType);
}
void bindEntries(ConfigurationPropertySource source, Map<Object, Object> map) {
if (source instanceof IterableConfigurationPropertySource iterableSource) {
for (ConfigurationPropertyName name : iterableSource) {
ConfigurationPropertyName entryName = getEntryName(source, name);
Object key = getContext().getConverter().convert(getKeyName(entryName), this.keyType);
Bindable<?> valueBindable = getValueBindable(name);
map.computeIfAbsent(key, (k) -> this.elementBinder.bind(entryName, valueBindable));
}
}
}
private Bindable<?> getValueBindable(ConfigurationPropertyName name) {
return (!isParentOf(name) && this.valueTreatedAsNestedMap) ? this.bindableMapType : this.bindableValueType;
}
private ConfigurationPropertyName getEntryName(ConfigurationPropertySource source,
ConfigurationPropertyName name) {
if (Collection.class.isAssignableFrom(this.resolvedValueType) || this.valueType.isArray()) {
return chopNameAtNumericIndex(name);
}
if (!isParentOf(name) && (this.valueTreatedAsNestedMap || !isScalarValue(source, name))) {
return name.chop(this.root.getNumberOfElements() + 1);
}
return name;
}
private boolean isParentOf(ConfigurationPropertyName name) {
return this.root.isParentOf(name);
}
private ConfigurationPropertyName chopNameAtNumericIndex(ConfigurationPropertyName name) {
int start = this.root.getNumberOfElements() + 1;
int size = name.getNumberOfElements();
for (int i = start; i < size; i++) {
if (name.isNumericIndex(i)) {
return name.chop(i);
}
}
return name;
}
private boolean isScalarValue(ConfigurationPropertySource source, ConfigurationPropertyName name) {
Class<?> resolved = this.valueType.resolve(Object.class);
if (!resolved.getName().startsWith("java.lang") && !resolved.isEnum()) {
return false;
}
ConfigurationProperty property = source.getConfigurationProperty(name);
if (property == null) {
return false;
}
Object value = property.getValue();
value = getContext().getPlaceholdersResolver().resolvePlaceholders(value);
return getContext().getConverter().canConvert(value, this.valueType);
}
private String getKeyName(ConfigurationPropertyName name) {
StringBuilder result = new StringBuilder();
for (int i = this.root.getNumberOfElements(); i < name.getNumberOfElements(); i++) {
if (!result.isEmpty()) {
result.append('.');
}
result.append(name.getElement(i, Form.ORIGINAL));
}
return result.toString();
}
}
Domain
Source
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free