mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-29 21:59:02 +00:00
Polish "Add property to enable Caffeine async cache mode"
Restructured to spring.cache.caffeine.cache-mode with an enum that can be "native" or "async". Also clarified in the documentation the scope of the property and that custom caches are not affected. See gh-51844
This commit is contained in:
+4
-1
@@ -223,7 +223,10 @@ If a javadoc:com.github.benmanes.caffeine.cache.CacheLoader[] bean is defined, i
|
||||
Since the javadoc:com.github.benmanes.caffeine.cache.CacheLoader[] is going to be associated with _all_ caches managed by the cache manager, it must be defined as `CacheLoader<Object, Object>`.
|
||||
The auto-configuration ignores any other generic type.
|
||||
|
||||
To expose asynchronous caches backed by Caffeine's javadoc:com.github.benmanes.caffeine.cache.AsyncCache[], adding support for `Cache.retrieve`, set configprop:spring.cache.caffeine.async[] to `true`.
|
||||
To enable the use of `Cache#retrieve`, an javadoc:com.github.benmanes.caffeine.cache.AsyncCache[] should be available.
|
||||
Such caches can be created explicitly with a `CacheManagerCustomizer` bean that calls `CaffeineCacheManager#registerCustomCache`.
|
||||
Alternatively, named caches and caches on demand can be async by setting configprop:spring.cache.caffeine.cache-mode[] to `async`.
|
||||
Regular, native, caches can still be configured explicitly using a customizer bean.
|
||||
|
||||
|
||||
|
||||
|
||||
+24
-10
@@ -116,17 +116,24 @@ public class CacheProperties {
|
||||
*/
|
||||
public static class Caffeine {
|
||||
|
||||
/**
|
||||
* Mode to use for configured cache names or caches created on demand.
|
||||
*/
|
||||
private CacheMode cacheMode = CacheMode.NATIVE;
|
||||
|
||||
/**
|
||||
* The spec to use to create caches. See CaffeineSpec for more details on the spec
|
||||
* format.
|
||||
*/
|
||||
private @Nullable String spec;
|
||||
|
||||
/**
|
||||
* Whether to expose asynchronous caches backed by Caffeine's AsyncCache, adding
|
||||
* support for Cache.retrieve.
|
||||
*/
|
||||
private boolean async;
|
||||
public CacheMode getCacheMode() {
|
||||
return this.cacheMode;
|
||||
}
|
||||
|
||||
public void setCacheMode(CacheMode cacheMode) {
|
||||
this.cacheMode = cacheMode;
|
||||
}
|
||||
|
||||
public @Nullable String getSpec() {
|
||||
return this.spec;
|
||||
@@ -136,12 +143,19 @@ public class CacheProperties {
|
||||
this.spec = spec;
|
||||
}
|
||||
|
||||
public boolean isAsync() {
|
||||
return this.async;
|
||||
}
|
||||
public enum CacheMode {
|
||||
|
||||
/**
|
||||
* Use regular caches backed by Caffeine's Cache.
|
||||
*/
|
||||
NATIVE,
|
||||
|
||||
/**
|
||||
* Use asynchronous caches backed by Caffeine's AsyncCache, adding support for
|
||||
* Cache.retrieve.
|
||||
*/
|
||||
ASYNC
|
||||
|
||||
public void setAsync(boolean async) {
|
||||
this.async = async;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-4
@@ -26,6 +26,7 @@ import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.cache.autoconfigure.CacheProperties.Caffeine.CacheMode;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.caffeine.CaffeineCacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -61,15 +62,18 @@ class CaffeineCacheConfiguration {
|
||||
ObjectProvider<Caffeine<Object, Object>> caffeine, ObjectProvider<CaffeineSpec> caffeineSpec,
|
||||
ObjectProvider<CacheLoader<Object, Object>> cacheLoader) {
|
||||
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
|
||||
cacheManager.setAsyncCacheMode(cacheProperties.getCaffeine().isAsync());
|
||||
setCacheBuilder(cacheProperties, caffeineSpec.getIfAvailable(), caffeine.getIfAvailable(), cacheManager);
|
||||
CacheProperties.Caffeine caffeineProperties = cacheProperties.getCaffeine();
|
||||
if (caffeineProperties.getCacheMode() == CacheMode.ASYNC) {
|
||||
cacheManager.setAsyncCacheMode(true);
|
||||
}
|
||||
setCacheBuilder(caffeineProperties, caffeineSpec.getIfAvailable(), caffeine.getIfAvailable(), cacheManager);
|
||||
cacheLoader.ifAvailable(cacheManager::setCacheLoader);
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
private void setCacheBuilder(CacheProperties cacheProperties, @Nullable CaffeineSpec caffeineSpec,
|
||||
private void setCacheBuilder(CacheProperties.Caffeine caffeineProperties, @Nullable CaffeineSpec caffeineSpec,
|
||||
@Nullable Caffeine<Object, Object> caffeine, CaffeineCacheManager cacheManager) {
|
||||
String specification = cacheProperties.getCaffeine().getSpec();
|
||||
String specification = caffeineProperties.getSpec();
|
||||
if (StringUtils.hasText(specification)) {
|
||||
cacheManager.setCacheSpecification(specification);
|
||||
}
|
||||
|
||||
+16
-17
@@ -81,6 +81,7 @@ import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.assertj.core.api.Assertions.assertThatNoException;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
@@ -815,27 +816,25 @@ class CacheAutoConfigurationTests extends AbstractCacheAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void caffeineCacheWithAsyncCacheMode() {
|
||||
this.contextRunner.withUserConfiguration(DefaultCacheConfiguration.class)
|
||||
.withPropertyValues("spring.cache.type=caffeine", "spring.cache.caffeine.async=true",
|
||||
"spring.cache.cacheNames=foo")
|
||||
.run((context) -> {
|
||||
CaffeineCacheManager manager = getCacheManager(context, CaffeineCacheManager.class);
|
||||
CaffeineCache foo = (CaffeineCache) manager.getCache("foo");
|
||||
assertThat(foo).isNotNull();
|
||||
assertThat(foo.getAsyncCache()).isNotNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void caffeineCacheWithoutAsyncCacheModeByDefault() {
|
||||
void caffeineCacheUsesNativeModeByDefault() {
|
||||
this.contextRunner.withUserConfiguration(DefaultCacheConfiguration.class)
|
||||
.withPropertyValues("spring.cache.type=caffeine", "spring.cache.cacheNames=foo")
|
||||
.run((context) -> {
|
||||
CaffeineCacheManager manager = getCacheManager(context, CaffeineCacheManager.class);
|
||||
CaffeineCache foo = (CaffeineCache) manager.getCache("foo");
|
||||
assertThat(foo).isNotNull();
|
||||
assertThatIllegalStateException().isThrownBy(foo::getAsyncCache);
|
||||
assertThat(manager.getCache("foo")).isInstanceOfSatisfying(CaffeineCache.class,
|
||||
(cache) -> assertThatIllegalStateException().isThrownBy(cache::getAsyncCache));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void caffeineCacheWithAsyncCacheMode() {
|
||||
this.contextRunner.withUserConfiguration(DefaultCacheConfiguration.class)
|
||||
.withPropertyValues("spring.cache.type=caffeine", "spring.cache.caffeine.cache-mode=async",
|
||||
"spring.cache.cacheNames=foo")
|
||||
.run((context) -> {
|
||||
CaffeineCacheManager manager = getCacheManager(context, CaffeineCacheManager.class);
|
||||
assertThat(manager.getCache("foo")).isInstanceOfSatisfying(CaffeineCache.class,
|
||||
(cache) -> assertThatNoException().isThrownBy(cache::getAsyncCache));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user