mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-29 21:59:02 +00:00
Merge pull request #51844 from hunseonglee
Closes gh-51844 * caffeine-async-cache-mode: Polish "Add property to enable Caffeine async cache mode" Add property to enable Caffeine async cache mode
This commit is contained in:
@@ -223,6 +223,11 @@ 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 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.
|
||||
|
||||
|
||||
|
||||
[[io.caching.provider.cache2k]]
|
||||
|
||||
+28
@@ -116,12 +116,25 @@ 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;
|
||||
|
||||
public CacheMode getCacheMode() {
|
||||
return this.cacheMode;
|
||||
}
|
||||
|
||||
public void setCacheMode(CacheMode cacheMode) {
|
||||
this.cacheMode = cacheMode;
|
||||
}
|
||||
|
||||
public @Nullable String getSpec() {
|
||||
return this.spec;
|
||||
}
|
||||
@@ -130,6 +143,21 @@ public class CacheProperties {
|
||||
this.spec = spec;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+8
-3
@@ -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,14 +62,18 @@ class CaffeineCacheConfiguration {
|
||||
ObjectProvider<Caffeine<Object, Object>> caffeine, ObjectProvider<CaffeineSpec> caffeineSpec,
|
||||
ObjectProvider<CacheLoader<Object, Object>> cacheLoader) {
|
||||
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
|
||||
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);
|
||||
}
|
||||
|
||||
+25
@@ -80,6 +80,8 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
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;
|
||||
@@ -813,6 +815,29 @@ class CacheAutoConfigurationTests extends AbstractCacheAutoConfigurationTests {
|
||||
.run(this::validateCaffeineCacheWithStats);
|
||||
}
|
||||
|
||||
@Test
|
||||
void caffeineCacheUsesNativeModeByDefault() {
|
||||
this.contextRunner.withUserConfiguration(DefaultCacheConfiguration.class)
|
||||
.withPropertyValues("spring.cache.type=caffeine", "spring.cache.cacheNames=foo")
|
||||
.run((context) -> {
|
||||
CaffeineCacheManager manager = getCacheManager(context, CaffeineCacheManager.class);
|
||||
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));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoConfiguredCacheManagerCanBeSwapped() {
|
||||
this.contextRunner.withUserConfiguration(CacheManagerPostProcessorConfiguration.class)
|
||||
|
||||
Reference in New Issue
Block a user