Commit 44d83215 authored by dreis2211's avatar dreis2211 Committed by Phillip Webb

Optimize CacheKey handling for immutable sources

Update `SpringIterableConfigurationPropertySource` so that cache keys
do not need to be checked if property sources are immutable.

See gh-16717
parent 071410c4
...@@ -25,6 +25,7 @@ import java.util.List; ...@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.core.env.EnumerablePropertySource; import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
...@@ -192,21 +193,37 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope ...@@ -192,21 +193,37 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope
private final Object key; private final Object key;
private CacheKey(Object key) { private final int size;
private final boolean unmodifiableKey;
private CacheKey(Object key, boolean unmodifiableKey) {
this.key = key; this.key = key;
this.size = calculateSize(key);
this.unmodifiableKey = unmodifiableKey;
} }
public CacheKey copy() { public CacheKey copy() {
return new CacheKey(copyKey(this.key)); return new CacheKey(copyKey(this.key), this.unmodifiableKey);
} }
private Object copyKey(Object key) { private Object copyKey(Object key) {
if (this.unmodifiableKey) {
return key;
}
if (key instanceof Set) { if (key instanceof Set) {
return new HashSet<Object>((Set<?>) key); return new HashSet<Object>((Set<?>) key);
} }
return ((String[]) key).clone(); return ((String[]) key).clone();
} }
private int calculateSize(Object key) {
if (key instanceof Set) {
return ((Set<?>) key).size();
}
return ((String[]) key).length;
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) { if (this == obj) {
...@@ -215,7 +232,11 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope ...@@ -215,7 +232,11 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope
if (obj == null || getClass() != obj.getClass()) { if (obj == null || getClass() != obj.getClass()) {
return false; return false;
} }
return ObjectUtils.nullSafeEquals(this.key, ((CacheKey) obj).key); CacheKey otherCacheKey = (CacheKey) obj;
if (this.size != otherCacheKey.size) {
return false;
}
return ObjectUtils.nullSafeEquals(this.key, otherCacheKey.key);
} }
@Override @Override
...@@ -225,9 +246,10 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope ...@@ -225,9 +246,10 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope
public static CacheKey get(EnumerablePropertySource<?> source) { public static CacheKey get(EnumerablePropertySource<?> source) {
if (source instanceof MapPropertySource) { if (source instanceof MapPropertySource) {
return new CacheKey(((MapPropertySource) source).getSource().keySet()); return new CacheKey(((MapPropertySource) source).getSource().keySet(),
source instanceof OriginTrackedMapPropertySource);
} }
return new CacheKey(source.getPropertyNames()); return new CacheKey(source.getPropertyNames(), false);
} }
} }
......
...@@ -25,6 +25,7 @@ import java.util.Set; ...@@ -25,6 +25,7 @@ import java.util.Set;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.origin.Origin; import org.springframework.boot.origin.Origin;
import org.springframework.boot.origin.OriginLookup; import org.springframework.boot.origin.OriginLookup;
import org.springframework.core.env.EnumerablePropertySource; import org.springframework.core.env.EnumerablePropertySource;
...@@ -160,7 +161,7 @@ public class SpringIterableConfigurationPropertySourceTests { ...@@ -160,7 +161,7 @@ public class SpringIterableConfigurationPropertySourceTests {
} }
@Test @Test
public void propertySourceKeyDataChangeInvalidatesCache() { public void simpleMapPropertySourceKeyDataChangeInvalidatesCache() {
// gh-13344 // gh-13344
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
map.put("key1", "value1"); map.put("key1", "value1");
...@@ -184,6 +185,18 @@ public class SpringIterableConfigurationPropertySourceTests { ...@@ -184,6 +185,18 @@ public class SpringIterableConfigurationPropertySourceTests {
source, DefaultPropertyMapper.INSTANCE); source, DefaultPropertyMapper.INSTANCE);
assertThat(adapter.stream().count()).isEqualTo(2); assertThat(adapter.stream().count()).isEqualTo(2);
map.setThrowException(true); map.setThrowException(true);
}
public void originTrackedMapPropertySourceKeyAdditionInvalidatesCache() {
// gh-13344
Map<String, Object> map = new LinkedHashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
EnumerablePropertySource<?> source = new OriginTrackedMapPropertySource("test",
map);
SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource(
source, DefaultPropertyMapper.INSTANCE);
assertThat(adapter.stream().count()).isEqualTo(2);
map.put("key3", "value3"); map.put("key3", "value3");
assertThat(adapter.stream().count()).isEqualTo(3); assertThat(adapter.stream().count()).isEqualTo(3);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment