Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 05ad955

Browse files
committed
Merge pull request #16717 from dreis2211
* pr/16717: Polish "Optimize CacheKey handling for immutable sources" Optimize CacheKey handling for immutable sources Closes gh-16717
2 parents 071410c + 3bfc923 commit 05ad955

File tree

5 files changed

+87
-7
lines changed

5 files changed

+87
-7
lines changed

‎spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySource.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@
2525
import java.util.Set;
2626
import java.util.stream.Stream;
2727

28+
import org.springframework.boot.env.OriginTrackedMapPropertySource;
2829
import org.springframework.core.env.EnumerablePropertySource;
2930
import org.springframework.core.env.MapPropertySource;
3031
import org.springframework.core.env.PropertySource;
32+
import org.springframework.core.env.StandardEnvironment;
3133
import org.springframework.core.env.SystemEnvironmentPropertySource;
3234
import org.springframework.util.ObjectUtils;
3335

@@ -190,13 +192,19 @@ public void setMappings(PropertyMapping[] mappings) {
190192

191193
private static final class CacheKey {
192194

195+
private static final CacheKey IMMUTABLE_PROPERTY_SOURCE = new CacheKey(
196+
new Object[0]);
197+
193198
private final Object key;
194199

195200
private CacheKey(Object key) {
196201
this.key = key;
197202
}
198203

199204
public CacheKey copy() {
205+
if (this == IMMUTABLE_PROPERTY_SOURCE) {
206+
return IMMUTABLE_PROPERTY_SOURCE;
207+
}
200208
return new CacheKey(copyKey(this.key));
201209
}
202210

@@ -215,7 +223,8 @@ public boolean equals(Object obj) {
215223
if (obj == null || getClass() != obj.getClass()) {
216224
return false;
217225
}
218-
return ObjectUtils.nullSafeEquals(this.key, ((CacheKey) obj).key);
226+
CacheKey otherCacheKey = (CacheKey) obj;
227+
return ObjectUtils.nullSafeEquals(this.key, otherCacheKey.key);
219228
}
220229

221230
@Override
@@ -224,12 +233,27 @@ public int hashCode() {
224233
}
225234

226235
public static CacheKey get(EnumerablePropertySource<?> source) {
236+
if (isImmutable(source)) {
237+
return IMMUTABLE_PROPERTY_SOURCE;
238+
}
227239
if (source instanceof MapPropertySource) {
228-
return new CacheKey(((MapPropertySource) source).getSource().keySet());
240+
MapPropertySource mapPropertySource = (MapPropertySource) source;
241+
return new CacheKey(mapPropertySource.getSource().keySet());
229242
}
230243
return new CacheKey(source.getPropertyNames());
231244
}
232245

246+
private static boolean isImmutable(EnumerablePropertySource<?> source) {
247+
if (source instanceof OriginTrackedMapPropertySource) {
248+
return ((OriginTrackedMapPropertySource) source).isImmutable();
249+
}
250+
if (StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME
251+
.equals(source.getName())) {
252+
return source.getSource() == System.getenv();
253+
}
254+
return false;
255+
}
256+
233257
}
234258

235259
}

‎spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/OriginTrackedMapPropertySource.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.springframework.boot.origin.OriginLookup;
2323
import org.springframework.boot.origin.OriginTrackedValue;
2424
import org.springframework.core.env.MapPropertySource;
25+
import org.springframework.core.env.PropertySource;
2526

2627
/**
2728
* {@link OriginLookup} backed by a {@link Map} containing {@link OriginTrackedValue
@@ -35,9 +36,28 @@
3536
public final class OriginTrackedMapPropertySource extends MapPropertySource
3637
implements OriginLookup<String> {
3738

38-
@SuppressWarnings({ "unchecked", "rawtypes" })
39+
private final boolean immutable;
40+
41+
/**
42+
* Create a new {@link OriginTrackedMapPropertySource} instance.
43+
* @param name the property source name
44+
* @param source the underlying map source
45+
*/
46+
@SuppressWarnings("rawtypes")
3947
public OriginTrackedMapPropertySource(String name, Map source) {
48+
this(name, source, false);
49+
}
50+
51+
/**
52+
* Create a new {@link OriginTrackedMapPropertySource} instance.
53+
* @param name the property source name
54+
* @param source the underlying map source
55+
* @param immutable if the underlying source is immutable and guaranteed not to change
56+
*/
57+
@SuppressWarnings({ "unchecked", "rawtypes" })
58+
public OriginTrackedMapPropertySource(String name, Map source, boolean immutable) {
4059
super(name, source);
60+
this.immutable = immutable;
4161
}
4262

4363
@Override
@@ -58,4 +78,13 @@ public Origin getOrigin(String name) {
5878
return null;
5979
}
6080

81+
/**
82+
* Return {@code true} if this {@link PropertySource} is immutable and has contents
83+
* that will never change.
84+
* @return if the property source is read only
85+
*/
86+
public boolean isImmutable() {
87+
return this.immutable;
88+
}
89+
6190
}

‎spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/PropertiesPropertySourceLoader.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ public List<PropertySource<?>> load(String name, Resource resource)
4848
if (properties.isEmpty()) {
4949
return Collections.emptyList();
5050
}
51-
return Collections
52-
.singletonList(newOriginTrackedMapPropertySource(name, properties));
51+
return Collections.singletonList(newOriginTrackedMapPropertySource(name,
52+
Collections.unmodifiableMap(properties), true));
5353
}
5454

5555
@SuppressWarnings({ "unchecked", "rawtypes" })

‎spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/YamlPropertySourceLoader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public List<PropertySource<?>> load(String name, Resource resource)
5555
for (int i = 0; i < loaded.size(); i++) {
5656
String documentNumber = (loaded.size() != 1) ? " (document #" + i + ")" : "";
5757
propertySources.add(new OriginTrackedMapPropertySource(name + documentNumber,
58-
loaded.get(i)));
58+
Collections.unmodifiableMap(loaded.get(i)), true));
5959
}
6060
return propertySources;
6161
}

‎spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySourceTests.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import org.junit.Test;
2727

28+
import org.springframework.boot.env.OriginTrackedMapPropertySource;
2829
import org.springframework.boot.origin.Origin;
2930
import org.springframework.boot.origin.OriginLookup;
3031
import org.springframework.core.env.EnumerablePropertySource;
@@ -160,7 +161,7 @@ public void containsDescendantOfShouldCheckSourceNames() {
160161
}
161162

162163
@Test
163-
public void propertySourceKeyDataChangeInvalidatesCache() {
164+
public void simpleMapPropertySourceKeyDataChangeInvalidatesCache() {
164165
// gh-13344
165166
Map<String, Object> map = new LinkedHashMap<>();
166167
map.put("key1", "value1");
@@ -184,10 +185,36 @@ public void concurrentModificationExceptionInvalidatesCache() {
184185
source, DefaultPropertyMapper.INSTANCE);
185186
assertThat(adapter.stream().count()).isEqualTo(2);
186187
map.setThrowException(true);
188+
}
189+
190+
public void originTrackedMapPropertySourceKeyAdditionInvalidatesCache() {
191+
// gh-13344
192+
Map<String, Object> map = new LinkedHashMap<>();
193+
map.put("key1", "value1");
194+
map.put("key2", "value2");
195+
EnumerablePropertySource<?> source = new OriginTrackedMapPropertySource("test",
196+
map);
197+
SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource(
198+
source, DefaultPropertyMapper.INSTANCE);
199+
assertThat(adapter.stream().count()).isEqualTo(2);
187200
map.put("key3", "value3");
188201
assertThat(adapter.stream().count()).isEqualTo(3);
189202
}
190203

204+
public void readOnlyOriginTrackedMapPropertySourceKeyAdditionDoesNotInvalidateCache() {
205+
// gh-16717
206+
Map<String, Object> map = new LinkedHashMap<>();
207+
map.put("key1", "value1");
208+
map.put("key2", "value2");
209+
EnumerablePropertySource<?> source = new OriginTrackedMapPropertySource("test",
210+
map, true);
211+
SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource(
212+
source, DefaultPropertyMapper.INSTANCE);
213+
assertThat(adapter.stream().count()).isEqualTo(2);
214+
map.put("key3", "value3");
215+
assertThat(adapter.stream().count()).isEqualTo(2);
216+
}
217+
191218
/**
192219
* Test {@link PropertySource} that's also an {@link OriginLookup}.
193220
*/

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /