diff --git a/spring-core/src/main/java/org/springframework/util/PlaceholderParser.java b/spring-core/src/main/java/org/springframework/util/PlaceholderParser.java index be9068271fd9..57ebe8f5d3ab 100644 --- a/spring-core/src/main/java/org/springframework/util/PlaceholderParser.java +++ b/spring-core/src/main/java/org/springframework/util/PlaceholderParser.java @@ -443,34 +443,30 @@ record SimplePlaceholderPart(String text, String key, @Nullable String fallback) @Override public String resolve(PartResolutionContext resolutionContext) { - String resolvedValue = resolveToText(resolutionContext, this.key); - if (resolvedValue != null) { - return resolvedValue; - } - else if (this.fallback != null) { - return this.fallback; - } - return resolutionContext.handleUnresolvablePlaceholder(this.key, this.text); + String resolvedKey = Part.resolveAll(this.keyParts, resolutionContext); + String value = resolveToText(resolutionContext, resolvedKey); + if (value != null) { + return value; + } else if (this.defaultParts != null) { + return Part.resolveAll(this.defaultParts, resolutionContext); + } + return resolutionContext.handleUnresolvablePlaceholder(resolvedKey, this.text); } - - @Nullable + private String resolveToText(PartResolutionContext resolutionContext, String text) { - String resolvedValue = resolutionContext.resolvePlaceholder(text); - if (resolvedValue != null) { - resolutionContext.flagPlaceholderAsVisited(text); - // Let's check if we need to recursively resolve that value - List nestedParts = resolutionContext.parse(resolvedValue); - String value = toText(nestedParts); - if (!isTextOnly(nestedParts)) { - value = new ParsedValue(resolvedValue, nestedParts).resolve(resolutionContext); - } - resolutionContext.removePlaceholder(text); - return value; - } - // Not found - return null; + String resolvedValue = resolutionContext.resolvePlaceholder(text); + if (resolvedValue != null) { + resolutionContext.flagPlaceholderAsVisited(text); + // Check for nested placeholders + List nestedParts = resolutionContext.parse(resolvedValue); + String value = Part.resolveAll(nestedParts, resolutionContext); + resolutionContext.removePlaceholder(text); + return value; + } + return null; } + private boolean isTextOnly(List parts) { return parts.stream().allMatch(TextPart.class::isInstance); }