Cache Class — spring-boot Architecture
Architecture documentation for the Cache class in SpringIterableConfigurationPropertySource.java from the spring-boot codebase.
Entity Profile
Relationship Graph
Source Code
core/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySource.java lines 219–367
private static class Cache {
private static final ConfigurationPropertyName[] EMPTY_NAMES_ARRAY = {};
private final PropertyMapper[] mappers;
private final boolean immutable;
private final boolean captureDescendants;
private final boolean systemEnvironmentSource;
private volatile @Nullable Data data;
Cache(PropertyMapper[] mappers, boolean immutable, boolean captureDescendants,
boolean systemEnvironmentSource) {
this.mappers = mappers;
this.immutable = immutable;
this.captureDescendants = captureDescendants;
this.systemEnvironmentSource = systemEnvironmentSource;
}
void update(EnumerablePropertySource<?> propertySource) {
if (this.data == null || !this.immutable) {
int count = 0;
while (true) {
try {
tryUpdate(propertySource);
return;
}
catch (ConcurrentModificationException ex) {
if (count++ > 10) {
throw ex;
}
}
}
}
}
private void tryUpdate(EnumerablePropertySource<?> propertySource) {
Data data = this.data;
String[] lastUpdated = (data != null) ? data.lastUpdated() : null;
String[] propertyNames = propertySource.getPropertyNames();
if (lastUpdated != null && Arrays.equals(lastUpdated, propertyNames)) {
return;
}
int size = propertyNames.length;
Map<ConfigurationPropertyName, Set<String>> mappings = cloneOrCreate(
(data != null) ? data.mappings() : null, size);
Map<String, ConfigurationPropertyName> reverseMappings = cloneOrCreate(
(data != null) ? data.reverseMappings() : null, size);
Set<ConfigurationPropertyName> descendants = (!this.captureDescendants) ? null : new HashSet<>();
Map<String, Object> systemEnvironmentCopy = (!this.systemEnvironmentSource) ? null
: copySource(propertySource);
for (PropertyMapper propertyMapper : this.mappers) {
for (String propertyName : propertyNames) {
if (!reverseMappings.containsKey(propertyName)) {
ConfigurationPropertyName configurationPropertyName = propertyMapper.map(propertyName);
if (configurationPropertyName != null && !configurationPropertyName.isEmpty()) {
add(mappings, configurationPropertyName, propertyName);
reverseMappings.put(propertyName, configurationPropertyName);
}
}
}
}
for (String propertyName : propertyNames) {
addParents(descendants, reverseMappings.get(propertyName));
}
ConfigurationPropertyName[] configurationPropertyNames = this.immutable
? reverseMappings.values().toArray(new ConfigurationPropertyName[0]) : null;
lastUpdated = this.immutable ? null : propertyNames;
this.data = new Data(mappings, reverseMappings, descendants, configurationPropertyNames,
systemEnvironmentCopy, lastUpdated);
}
@SuppressWarnings("unchecked")
private HashMap<String, Object> copySource(EnumerablePropertySource<?> propertySource) {
return new HashMap<>((Map<String, Object>) propertySource.getSource());
}
private <K, V> Map<K, V> cloneOrCreate(@Nullable Map<K, V> source, int size) {
return (source != null) ? new LinkedHashMap<>(source) : new LinkedHashMap<>(size);
}
private void addParents(@Nullable Set<ConfigurationPropertyName> descendants,
@Nullable ConfigurationPropertyName name) {
if (descendants == null || name == null || name.isEmpty()) {
return;
}
ConfigurationPropertyName parent = name.getParent();
while (!parent.isEmpty()) {
if (!descendants.add(parent)) {
return;
}
parent = parent.getParent();
}
}
private <K, T> void add(Map<K, Set<T>> map, K key, T value) {
map.computeIfAbsent(key, (k) -> new HashSet<>()).add(value);
}
Set<String> getMapped(ConfigurationPropertyName configurationPropertyName) {
Data data = this.data;
Assert.state(data != null, "'data' must not be null");
return data.mappings().getOrDefault(configurationPropertyName, Collections.emptySet());
}
@Nullable ConfigurationPropertyName[] getConfigurationPropertyNames(String[] propertyNames) {
Data data = this.data;
Assert.state(data != null, "'data' must not be null");
@Nullable ConfigurationPropertyName[] names = data.configurationPropertyNames();
if (names != null) {
return names;
}
Map<String, ConfigurationPropertyName> reverseMappings = data.reverseMappings();
if (reverseMappings == null || reverseMappings.isEmpty()) {
return EMPTY_NAMES_ARRAY;
}
names = new ConfigurationPropertyName[propertyNames.length];
for (int i = 0; i < propertyNames.length; i++) {
names[i] = reverseMappings.get(propertyNames[i]);
}
return names;
}
@Nullable Set<ConfigurationPropertyName> getDescendants() {
Data data = this.data;
Assert.state(data != null, "'data' must not be null");
return data.descendants();
}
@Nullable Object getSystemEnvironmentProperty(String name) {
Data data = this.data;
Assert.state(data != null, "'data' must not be null");
Map<String, Object> systemEnvironmentCopy = data.systemEnvironmentCopy();
Assert.state(systemEnvironmentCopy != null, "'systemEnvironmentCopy' must not be null");
return systemEnvironmentCopy.get(name);
}
private record Data(Map<ConfigurationPropertyName, Set<String>> mappings,
Map<String, ConfigurationPropertyName> reverseMappings,
@Nullable Set<ConfigurationPropertyName> descendants,
ConfigurationPropertyName @Nullable [] configurationPropertyNames,
@Nullable Map<String, Object> systemEnvironmentCopy, String @Nullable [] lastUpdated) {
}
}
Domain
Source
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free