Skip to content

Commit 06658c3

Browse files
committed
Restore zero capacity support in ConcurrentLruCache
Since the rewrite of ConcurrentLruCache in Spring Framework 6.0, an attempt to create a ConcurrentLruCache with zero capacity results in an IllegalArgumentException even though the documentation states that zero capacity indicates "no caching, always generating a new value". This commit restores the ability to configure a ConcurrentLruCache with zero capacity and introduces corresponding tests (which were first verified against the 5.3.x branch to ensure backward compatibility). See gh-26320 Closes gh-31317
1 parent a37abd5 commit 06658c3

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

spring-core/src/main/java/org/springframework/util/ConcurrentLruCache.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -81,7 +81,7 @@ public ConcurrentLruCache(int capacity, Function<K, V> generator) {
8181
}
8282

8383
private ConcurrentLruCache(int capacity, Function<K, V> generator, int concurrencyLevel) {
84-
Assert.isTrue(capacity > 0, "Capacity must be > 0");
84+
Assert.isTrue(capacity >= 0, "Capacity must be >= 0");
8585
this.capacity = capacity;
8686
this.cache = new ConcurrentHashMap<>(16, 0.75f, concurrencyLevel);
8787
this.generator = generator;
@@ -95,6 +95,9 @@ private ConcurrentLruCache(int capacity, Function<K, V> generator, int concurren
9595
* @return the cached or newly generated value
9696
*/
9797
public V get(K key) {
98+
if (this.capacity == 0) {
99+
return this.generator.apply(key);
100+
}
98101
final Node<K, V> node = this.cache.get(key);
99102
if (node == null) {
100103
V value = this.generator.apply(key);

spring-core/src/test/java/org/springframework/util/ConcurrentLruCacheTests.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,13 +22,38 @@
2222

2323
/**
2424
* Tests for {@link ConcurrentLruCache}.
25+
*
2526
* @author Juergen Hoeller
27+
* @author Sam Brannen
2628
*/
2729
class ConcurrentLruCacheTests {
2830

2931
private final ConcurrentLruCache<String, String> cache = new ConcurrentLruCache<>(2, key -> key + "value");
3032

3133

34+
@Test
35+
void zeroCapacity() {
36+
ConcurrentLruCache<String, String> cache = new ConcurrentLruCache<>(0, key -> key + "value");
37+
38+
assertThat(cache.capacity()).isZero();
39+
assertThat(cache.size()).isZero();
40+
41+
assertThat(cache.get("k1")).isEqualTo("k1value");
42+
assertThat(cache.size()).isZero();
43+
assertThat(cache.contains("k1")).isFalse();
44+
45+
assertThat(cache.get("k2")).isEqualTo("k2value");
46+
assertThat(cache.size()).isZero();
47+
assertThat(cache.contains("k1")).isFalse();
48+
assertThat(cache.contains("k2")).isFalse();
49+
50+
assertThat(cache.get("k3")).isEqualTo("k3value");
51+
assertThat(cache.size()).isZero();
52+
assertThat(cache.contains("k1")).isFalse();
53+
assertThat(cache.contains("k2")).isFalse();
54+
assertThat(cache.contains("k3")).isFalse();
55+
}
56+
3257
@Test
3358
void getAndSize() {
3459
assertThat(this.cache.capacity()).isEqualTo(2);

0 commit comments

Comments
 (0)