Cache property mappings in ConfigurationPropertyName
Relocate `SystemEnvironmentPropertyMapper` methods into `ConfigurationPropertyName` so that they can be cached to improve performance Closes gh-44858
This commit is contained in:
parent
81dee54137
commit
ae6908e4d8
|
@ -20,8 +20,10 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.IntFunction;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
@ -63,10 +65,14 @@ public final class ConfigurationPropertyName implements Comparable<Configuration
|
||||||
|
|
||||||
private final CharSequence[] uniformElements;
|
private final CharSequence[] uniformElements;
|
||||||
|
|
||||||
private String string;
|
|
||||||
|
|
||||||
private int hashCode;
|
private int hashCode;
|
||||||
|
|
||||||
|
private String[] string = new String[ToStringFormat.values().length];
|
||||||
|
|
||||||
|
private Boolean hasDashedElement;
|
||||||
|
|
||||||
|
private ConfigurationPropertyName systemEnvironmentLegacyName;
|
||||||
|
|
||||||
private ConfigurationPropertyName(Elements elements) {
|
private ConfigurationPropertyName(Elements elements) {
|
||||||
this.elements = elements;
|
this.elements = elements;
|
||||||
this.uniformElements = new CharSequence[elements.getSize()];
|
this.uniformElements = new CharSequence[elements.getSize()];
|
||||||
|
@ -525,15 +531,41 @@ public final class ConfigurationPropertyName implements Comparable<Configuration
|
||||||
return hashCode;
|
return hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
ConfigurationPropertyName asSystemEnvironmentLegacyName() {
|
||||||
public String toString() {
|
ConfigurationPropertyName name = this.systemEnvironmentLegacyName;
|
||||||
if (this.string == null) {
|
if (name == null) {
|
||||||
this.string = buildToString();
|
name = ConfigurationPropertyName
|
||||||
|
.ofIfValid(buildSimpleToString('.', (i) -> getElement(i, Form.DASHED).replace('-', '.')));
|
||||||
|
this.systemEnvironmentLegacyName = (name != null) ? name : EMPTY;
|
||||||
}
|
}
|
||||||
return this.string;
|
return (name != EMPTY) ? name : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String buildToString() {
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return toString(ToStringFormat.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
String toString(ToStringFormat format) {
|
||||||
|
String string = this.string[format.ordinal()];
|
||||||
|
if (string == null) {
|
||||||
|
string = buildToString(format);
|
||||||
|
this.string[format.ordinal()] = string;
|
||||||
|
}
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildToString(ToStringFormat format) {
|
||||||
|
return switch (format) {
|
||||||
|
case DEFAULT -> buildDefaultToString();
|
||||||
|
case SYSTEM_ENVIRONMENT ->
|
||||||
|
buildSimpleToString('_', (i) -> getElement(i, Form.UNIFORM).toUpperCase(Locale.ENGLISH));
|
||||||
|
case LEGACY_SYSTEM_ENVIRONMENT -> buildSimpleToString('_',
|
||||||
|
(i) -> getElement(i, Form.ORIGINAL).replace('-', '_').toUpperCase(Locale.ENGLISH));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildDefaultToString() {
|
||||||
if (this.elements.canShortcutWithSource(ElementType.UNIFORM, ElementType.DASHED)) {
|
if (this.elements.canShortcutWithSource(ElementType.UNIFORM, ElementType.DASHED)) {
|
||||||
return this.elements.getSource().toString();
|
return this.elements.getSource().toString();
|
||||||
}
|
}
|
||||||
|
@ -556,6 +588,32 @@ public final class ConfigurationPropertyName implements Comparable<Configuration
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String buildSimpleToString(char joinChar, IntFunction<String> elementConverter) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for (int i = 0; i < getNumberOfElements(); i++) {
|
||||||
|
if (!result.isEmpty()) {
|
||||||
|
result.append(joinChar);
|
||||||
|
}
|
||||||
|
result.append(elementConverter.apply(i));
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasDashedElement() {
|
||||||
|
Boolean hasDashedElement = this.hasDashedElement;
|
||||||
|
if (hasDashedElement != null) {
|
||||||
|
return hasDashedElement;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < getNumberOfElements(); i++) {
|
||||||
|
if (getElement(i, Form.DASHED).indexOf('-') != -1) {
|
||||||
|
this.hasDashedElement = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.hasDashedElement = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if the given name is valid. If this method returns {@code true} then the
|
* Returns if the given name is valid. If this method returns {@code true} then the
|
||||||
* name may be used with {@link #of(CharSequence)} without throwing an exception.
|
* name may be used with {@link #of(CharSequence)} without throwing an exception.
|
||||||
|
@ -1132,4 +1190,13 @@ public final class ConfigurationPropertyName implements Comparable<Configuration
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats for {@code toString}.
|
||||||
|
*/
|
||||||
|
enum ToStringFormat {
|
||||||
|
|
||||||
|
DEFAULT, SYSTEM_ENVIRONMENT, LEGACY_SYSTEM_ENVIRONMENT
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -22,7 +22,7 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.function.BiPredicate;
|
import java.util.function.BiPredicate;
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName.Form;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyName.ToStringFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link PropertyMapper} for system environment variables. Names are mapped by removing
|
* {@link PropertyMapper} for system environment variables. Names are mapped by removing
|
||||||
|
@ -42,44 +42,14 @@ final class SystemEnvironmentPropertyMapper implements PropertyMapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> map(ConfigurationPropertyName configurationPropertyName) {
|
public List<String> map(ConfigurationPropertyName configurationPropertyName) {
|
||||||
String name = convertName(configurationPropertyName);
|
String name = configurationPropertyName.toString(ToStringFormat.SYSTEM_ENVIRONMENT);
|
||||||
String legacyName = convertLegacyName(configurationPropertyName);
|
String legacyName = configurationPropertyName.toString(ToStringFormat.LEGACY_SYSTEM_ENVIRONMENT);
|
||||||
if (name.equals(legacyName)) {
|
if (name.equals(legacyName)) {
|
||||||
return Collections.singletonList(name);
|
return Collections.singletonList(name);
|
||||||
}
|
}
|
||||||
return Arrays.asList(name, legacyName);
|
return Arrays.asList(name, legacyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String convertName(ConfigurationPropertyName name) {
|
|
||||||
return convertName(name, name.getNumberOfElements());
|
|
||||||
}
|
|
||||||
|
|
||||||
private String convertName(ConfigurationPropertyName name, int numberOfElements) {
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
for (int i = 0; i < numberOfElements; i++) {
|
|
||||||
if (!result.isEmpty()) {
|
|
||||||
result.append('_');
|
|
||||||
}
|
|
||||||
result.append(name.getElement(i, Form.UNIFORM).toUpperCase(Locale.ENGLISH));
|
|
||||||
}
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String convertLegacyName(ConfigurationPropertyName name) {
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
for (int i = 0; i < name.getNumberOfElements(); i++) {
|
|
||||||
if (!result.isEmpty()) {
|
|
||||||
result.append('_');
|
|
||||||
}
|
|
||||||
result.append(convertLegacyNameElement(name.getElement(i, Form.ORIGINAL)));
|
|
||||||
}
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object convertLegacyNameElement(String element) {
|
|
||||||
return element.replace('-', '_').toUpperCase(Locale.ENGLISH);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigurationPropertyName map(String propertySourceName) {
|
public ConfigurationPropertyName map(String propertySourceName) {
|
||||||
return convertName(propertySourceName);
|
return convertName(propertySourceName);
|
||||||
|
@ -113,31 +83,11 @@ final class SystemEnvironmentPropertyMapper implements PropertyMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLegacyAncestorOf(ConfigurationPropertyName name, ConfigurationPropertyName candidate) {
|
private boolean isLegacyAncestorOf(ConfigurationPropertyName name, ConfigurationPropertyName candidate) {
|
||||||
if (!hasDashedEntries(name)) {
|
if (!name.hasDashedElement()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ConfigurationPropertyName legacyCompatibleName = buildLegacyCompatibleName(name);
|
ConfigurationPropertyName legacyCompatibleName = name.asSystemEnvironmentLegacyName();
|
||||||
return legacyCompatibleName != null && legacyCompatibleName.isAncestorOf(candidate);
|
return legacyCompatibleName != null && legacyCompatibleName.isAncestorOf(candidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigurationPropertyName buildLegacyCompatibleName(ConfigurationPropertyName name) {
|
|
||||||
StringBuilder legacyCompatibleName = new StringBuilder();
|
|
||||||
for (int i = 0; i < name.getNumberOfElements(); i++) {
|
|
||||||
if (i != 0) {
|
|
||||||
legacyCompatibleName.append('.');
|
|
||||||
}
|
|
||||||
legacyCompatibleName.append(name.getElement(i, Form.DASHED).replace('-', '.'));
|
|
||||||
}
|
|
||||||
return ConfigurationPropertyName.ofIfValid(legacyCompatibleName);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean hasDashedEntries(ConfigurationPropertyName name) {
|
|
||||||
for (int i = 0; i < name.getNumberOfElements(); i++) {
|
|
||||||
if (name.getElement(i, Form.DASHED).indexOf('-') != -1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue