如何使用Spring Boot CacheManager搭配Caffeine实现支持@Cacheable的异步缓存
Spring Boot CacheManager 结合 Caffeine 异步缓存的实现方案
核心结论
- Spring Boot 2.x 及更低版本中,官方
CacheManager抽象仅支持同步缓存API,无法直接适配Caffeine的AsyncCache/AsyncCacheLoader,也不能直接用@Cacheable注解标注返回CompletableFuture的异步方法,这就是异步调用异常的核心原因。 - Spring 6.0+ / Spring Boot 3.0+ 版本新增了异步缓存原生支持,
CacheManager扩展了异步能力,可直接对接Caffeine异步缓存,配合@Cacheable使用无需手动封装异步逻辑。
Spring Boot 3.x 版本实现步骤
1. 引入依赖
<!-- 缓存启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <!-- Caffeine 缓存依赖 --> <dependency> <groupId>com.github.benmanes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency>
2. 配置异步缓存管理器
通过CaffeineAsyncCacheManager绑定自定义的AsyncCacheLoader,配置缓存过期、容量等参数:
import com.github.benmanes.caffeine.cache.AsyncCacheLoader; import com.github.benmanes.caffeine.cache.Caffeine; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.caffeine.CaffeineAsyncCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; @Configuration @EnableCaching public class AsyncCacheConfig { @Bean public CacheManager asyncCacheManager() { // 自定义异步缓存加载器,缓存未命中时触发 AsyncCacheLoader<Object, Object> cacheLoader = new AsyncCacheLoader<>() { @Override public CompletableFuture<?> asyncLoad(Object key, Executor executor) { // 此处可定义全局默认加载逻辑,也可直接省略,使用@Cacheable标注方法的业务逻辑 return CompletableFuture.supplyAsync(() -> loadDataByKey(key), executor); } }; // 构建异步缓存管理器 return CaffeineAsyncCacheManager.builder() .cacheNames("userCache", "orderCache") .withCacheConfiguration("userCache", Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .maximumSize(1000) .buildAsync(cacheLoader)) .withCacheConfiguration("orderCache", Caffeine.newBuilder() .expireAfterWrite(5, TimeUnit.MINUTES) .maximumSize(2000) .buildAsync(cacheLoader)) .build(); } private Object loadDataByKey(Object key) { // 模拟从数据库/第三方接口加载数据的逻辑 return null; } }
3. 结合@Cacheable使用
在需要缓存的异步方法上添加@Cacheable注解,指定使用异步缓存管理器即可:
import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.concurrent.CompletableFuture; @Service public class UserService { @Cacheable(cacheNames = "userCache", cacheManager = "asyncCacheManager") public CompletableFuture<User> queryUserById(Long userId) { // 模拟异步业务查询逻辑 return CompletableFuture.supplyAsync(() -> { // 实际业务查询代码 return userMapper.selectById(userId); }); } }
Spring Boot 2.x 版本兼容方案
如果无法升级到3.x版本,无法通过官方CacheManager和@Cacheable实现异步缓存,推荐两种处理方案:
- 直接在业务层手动注入
AsyncCache实例,自行封装缓存读写逻辑,跳过Spring Cache抽象层 - 自定义
Cache实现类,包装CaffeineAsyncCache的API,自行适配Spring的同步Cache接口,不过这种方案需要处理异步转同步的阻塞逻辑,不推荐高并发场景使用
内容的提问来源于stack exchange,提问作者Béatrice Cassistat
相关产品推荐
相关产品推荐

