From 64318336c45964fe53b46f57bda34e7603d0dfc8 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Sat, 22 Mar 2025 21:30:14 -0700 Subject: [PATCH] Polish SpringIterableConfigurationPropertySource --- ...ngIterableConfigurationPropertySource.java | 94 ++++++++++--------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySource.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySource.java index a2af54f1fe..d1e5f63daf 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySource.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySource.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,7 +55,7 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope private final BiPredicate ancestorOfCheck; - private final SoftReferenceConfigurationPropertyCache cache; + private final SoftReferenceConfigurationPropertyCache cache; private volatile ConfigurationPropertyName[] configurationPropertyNames; @@ -101,7 +101,7 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope if (configurationProperty != null) { return configurationProperty; } - for (String candidate : getMappings().getMapped(name)) { + for (String candidate : getCache().getMapped(name)) { Object value = getPropertySource().getProperty(candidate); if (value != null) { Origin origin = PropertySourceOrigin.get(getPropertySource(), candidate); @@ -129,7 +129,7 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope return result; } if (this.ancestorOfCheck == PropertyMapper.DEFAULT_ANCESTOR_OF_CHECK) { - return getMappings().containsDescendantOf(name, this.ancestorOfCheck); + return getCache().containsDescendantOf(name, this.ancestorOfCheck); } ConfigurationPropertyName[] candidates = getConfigurationPropertyNames(); for (ConfigurationPropertyName candidate : candidates) { @@ -142,29 +142,29 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope private ConfigurationPropertyName[] getConfigurationPropertyNames() { if (!isImmutablePropertySource()) { - return getMappings().getConfigurationPropertyNames(getPropertySource().getPropertyNames()); + return getCache().getConfigurationPropertyNames(getPropertySource().getPropertyNames()); } ConfigurationPropertyName[] configurationPropertyNames = this.configurationPropertyNames; if (configurationPropertyNames == null) { - configurationPropertyNames = getMappings() + configurationPropertyNames = getCache() .getConfigurationPropertyNames(getPropertySource().getPropertyNames()); this.configurationPropertyNames = configurationPropertyNames; } return configurationPropertyNames; } - private Mappings getMappings() { - return this.cache.get(this::createMappings, this::updateMappings); + private Cache getCache() { + return this.cache.get(this::createCache, this::updateCache); } - private Mappings createMappings() { - return new Mappings(getMappers(), isImmutablePropertySource(), + private Cache createCache() { + return new Cache(getMappers(), isImmutablePropertySource(), this.ancestorOfCheck == PropertyMapper.DEFAULT_ANCESTOR_OF_CHECK); } - private Mappings updateMappings(Mappings mappings) { - mappings.updateMappings(getPropertySource()::getPropertyNames); - return mappings; + private Cache updateCache(Cache cache) { + cache.update(getPropertySource()::getPropertyNames); + return cache; } private boolean isImmutablePropertySource() { @@ -183,7 +183,7 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope return (EnumerablePropertySource) super.getPropertySource(); } - private static class Mappings { + private static class Cache { private static final ConfigurationPropertyName[] EMPTY_NAMES_ARRAY = {}; @@ -191,30 +191,22 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope private final boolean immutable; - private final boolean trackDescendants; + private final boolean captureDescendants; - private volatile Map> mappings; + private volatile Data data; - private volatile Map reverseMappings; - - private volatile Map> descendants; - - private volatile ConfigurationPropertyName[] configurationPropertyNames; - - private volatile String[] lastUpdated; - - Mappings(PropertyMapper[] mappers, boolean immutable, boolean trackDescendants) { + Cache(PropertyMapper[] mappers, boolean immutable, boolean captureDescendants) { this.mappers = mappers; this.immutable = immutable; - this.trackDescendants = trackDescendants; + this.captureDescendants = captureDescendants; } - void updateMappings(Supplier propertyNames) { - if (this.mappings == null || !this.immutable) { + void update(Supplier propertyNames) { + if (this.data == null || !this.immutable) { int count = 0; while (true) { try { - updateMappings(propertyNames.get()); + tryUpdate(propertyNames.get()); return; } catch (ConcurrentModificationException ex) { @@ -226,16 +218,19 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope } } - private void updateMappings(String[] propertyNames) { - String[] lastUpdated = this.lastUpdated; + private void tryUpdate(String[] propertyNames) { + Data data = this.data; + String[] lastUpdated = (data != null) ? data.lastUpdated() : null; if (lastUpdated != null && Arrays.equals(lastUpdated, propertyNames)) { return; } int size = propertyNames.length; - Map> mappings = cloneOrCreate(this.mappings, size); - Map reverseMappings = cloneOrCreate(this.reverseMappings, size); - Map> descendants = cloneOrCreate(this.descendants, - size); + Map> mappings = cloneOrCreate( + (data != null) ? data.mappings() : null, size); + Map reverseMappings = cloneOrCreate( + (data != null) ? data.reverseMappings() : null, size); + Map> descendants = cloneOrCreate( + (data != null) ? data.descendants() : null, size); for (PropertyMapper propertyMapper : this.mappers) { for (String propertyName : propertyNames) { if (!reverseMappings.containsKey(propertyName)) { @@ -243,19 +238,17 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope if (configurationPropertyName != null && !configurationPropertyName.isEmpty()) { add(mappings, configurationPropertyName, propertyName); reverseMappings.put(propertyName, configurationPropertyName); - if (this.trackDescendants) { + if (this.captureDescendants) { addParents(descendants, configurationPropertyName); } } } } } - this.mappings = mappings; - this.reverseMappings = reverseMappings; - this.descendants = descendants; - this.lastUpdated = this.immutable ? null : propertyNames; - this.configurationPropertyNames = this.immutable + ConfigurationPropertyName[] configurationPropertyNames = this.immutable ? reverseMappings.values().toArray(new ConfigurationPropertyName[0]) : null; + lastUpdated = this.immutable ? null : propertyNames; + this.data = new Data(mappings, reverseMappings, descendants, configurationPropertyNames, lastUpdated); } private Map cloneOrCreate(Map source, int size) { @@ -276,15 +269,16 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope } Set getMapped(ConfigurationPropertyName configurationPropertyName) { - return this.mappings.getOrDefault(configurationPropertyName, Collections.emptySet()); + return this.data.mappings().getOrDefault(configurationPropertyName, Collections.emptySet()); } ConfigurationPropertyName[] getConfigurationPropertyNames(String[] propertyNames) { - ConfigurationPropertyName[] names = this.configurationPropertyNames; + Data data = this.data; + ConfigurationPropertyName[] names = data.configurationPropertyNames(); if (names != null) { return names; } - Map reverseMappings = this.reverseMappings; + Map reverseMappings = data.reverseMappings(); if (reverseMappings == null || reverseMappings.isEmpty()) { return EMPTY_NAMES_ARRAY; } @@ -297,10 +291,11 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope ConfigurationPropertyState containsDescendantOf(ConfigurationPropertyName name, BiPredicate ancestorOfCheck) { - if (name.isEmpty() && !this.descendants.isEmpty()) { + Data data = this.data; + if (name.isEmpty() && !data.descendants().isEmpty()) { return ConfigurationPropertyState.PRESENT; } - Set candidates = this.descendants.getOrDefault(name, Collections.emptySet()); + Set candidates = data.descendants().getOrDefault(name, Collections.emptySet()); for (ConfigurationPropertyName candidate : candidates) { if (ancestorOfCheck.test(name, candidate)) { return ConfigurationPropertyState.PRESENT; @@ -309,6 +304,13 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope return ConfigurationPropertyState.ABSENT; } + private record Data(Map> mappings, + Map reverseMappings, + Map> descendants, + ConfigurationPropertyName[] configurationPropertyNames, String[] lastUpdated) { + + } + } /**