diff --git a/spring-context-support/src/main/java/org/springframework/cache/caffeine/CaffeineCacheManager.java b/spring-context-support/src/main/java/org/springframework/cache/caffeine/CaffeineCacheManager.java index 9087df30efa3..75a89b196d6d 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/caffeine/CaffeineCacheManager.java +++ b/spring-context-support/src/main/java/org/springframework/cache/caffeine/CaffeineCacheManager.java @@ -106,9 +106,16 @@ public CaffeineCacheManager(String... cacheNames) { * with no creation of further cache regions at runtime. *

Calling this with a {@code null} collection argument resets the * mode to 'dynamic', allowing for further creation of caches again. + *

Note: Switching to static mode will remove all dynamically created + * caches, while preserving custom caches registered via + * {@link #registerCustomCache(String, com.github.benmanes.caffeine.cache.Cache)}. */ public void setCacheNames(@Nullable Collection cacheNames) { if (cacheNames != null) { + // Remove all non-custom caches before setting up static caches + this.cacheMap.keySet().retainAll(this.customCacheNames); + + // Add the specified static caches for (String name : cacheNames) { this.cacheMap.put(name, createCaffeineCache(name)); } diff --git a/spring-context-support/src/test/java/org/springframework/cache/caffeine/CaffeineCacheManagerTests.java b/spring-context-support/src/test/java/org/springframework/cache/caffeine/CaffeineCacheManagerTests.java index 1f4bb58c5239..6c6bf569d7ae 100644 --- a/spring-context-support/src/test/java/org/springframework/cache/caffeine/CaffeineCacheManagerTests.java +++ b/spring-context-support/src/test/java/org/springframework/cache/caffeine/CaffeineCacheManagerTests.java @@ -16,6 +16,8 @@ package org.springframework.cache.caffeine; +import java.util.Arrays; +import java.util.List; import java.util.concurrent.CompletableFuture; import com.github.benmanes.caffeine.cache.CacheLoader; @@ -284,6 +286,68 @@ void setCacheNameNullRestoreDynamicMode() { assertThat(cm.getCache("someCache")).isNotNull(); } + @Test + void setCacheNameShouldRemovePreviousDynamicCaches() { + CaffeineCacheManager manager = new CaffeineCacheManager(); + + // Given: Dynamic mode with some caches + manager.getCache("dynamicCache1"); + manager.getCache("dynamicCache2"); + assertThat(manager.getCacheNames()) + .containsExactlyInAnyOrder("dynamicCache1", "dynamicCache2"); + + // When: Switch to static mode + manager.setCacheNames(Arrays.asList("staticCache1", "staticCache2")); + + // Then: Only static caches should exist + assertThat(manager.getCacheNames()) + .containsExactlyInAnyOrder("staticCache1", "staticCache2") + .as("Dynamic caches should be removed when switching to static mode"); + + // And: Dynamic caches should not be accessible + assertThat(manager.getCache("dynamicCache1")).isNull(); + assertThat(manager.getCache("dynamicCache2")).isNull(); + } + + @Test + void setCacheNamesShouldPreserveCustomCaches() { + CaffeineCacheManager manager = new CaffeineCacheManager(); + + // Given: Custom cache registered + com.github.benmanes.caffeine.cache.Cache customNativeCache = Caffeine.newBuilder().maximumSize(100).build(); + manager.registerCustomCache("customCache", customNativeCache); + + // And: Dynamic cache created + manager.getCache("dynamicCache"); + + // When: Switch to static mode + manager.setCacheNames(List.of("staticCache")); + + // Then: Custom cache preserved, dynamic cache removed + assertThat(manager.getCacheNames()) + .contains("customCache", "staticCache") + .doesNotContain("dynamicCache"); + } + + @Test + void switchingBetweenDynamicAndStaticMode() { + CaffeineCacheManager manager = new CaffeineCacheManager(); + + // Dynamic → Static + manager.getCache("dynamicCache1"); + manager.setCacheNames(List.of("staticCache1")); + assertThat(manager.getCacheNames()).containsExactly("staticCache1"); + + // Static → Dynamic + manager.setCacheNames(null); // Re-enable dynamic mode + manager.getCache("dynamicCache2"); + assertThat(manager.getCacheNames()).contains("staticCache1", "dynamicCache2"); + + // Dynamic → Static again + manager.setCacheNames(List.of("staticCache2")); + assertThat(manager.getCacheNames()).containsExactly("staticCache2"); + } + @Test void cacheLoaderUseLoadingCache() { CaffeineCacheManager cm = new CaffeineCacheManager("c1");