Spring Boot 中实现单次调用写入多个缓存的完整方案

本文详解如何在 Spring Cache 中通过一次业务方法调用,将同一份结果(如客户标识对象)同时写入多个命名缓存(如按 customerID 和 accountNumber 分别缓存),避免重复远程调用,提升多维度查询场景下的缓存命中率。

本文详解如何在 Spring Cache 中通过一次业务方法调用,将同一份结果(如客户标识对象)同时写入多个命名缓存(如按 customerID 和 accountNumber 分别缓存),避免重复远程调用,提升多维度查询场景下的缓存命中率。

在基于 Spring 的微服务中,常遇到「一个实体可通过多种唯一键查询」的场景:例如客户信息既可通过 customerId(Long 类型)获取,也可通过 accountNumber(String 类型)获取。理想情况下,首次任一维度查询触发远程调用后,应自动将结果同步写入两个缓存,使后续任意维度查询均可直接命中——但 Spring 原生 @Cacheable 仅支持单缓存写入,无法原生满足该需求。本文提供生产就绪的解决方案。

✅ 核心思路:混合使用 @Cacheable + 显式 CacheManager 操作

最简洁、可控且无需引入额外依赖的方式是:

? 示例实现

@Service
@RequiredArgsConstructor
public class CachedIdentifiersService {

    private final LazyIdentifiersService slowService;
    private final CacheManager cacheManager;

    // 获取缓存实例(推荐在构造时初始化,避免每次调用 getCache())
    private final Cache cacheById = cacheManager.getCache("identifiers_cache_by_customer_id");
    private final Cache cacheByAccount = cacheManager.getCache("identifiers_cache_by_account_number");

    @Cacheable(value = "identifiers_cache_by_customer_id", key = "#customerId")
    public Identifiers getIdentifiers(Long customerId) {
        Identifiers identifiers = slowService.getIdentifiers();
        // ✅ 主动写入 accountNumber 缓存
        if (identifiers != null && identifiers.getAccountNumber() != null) {
            cacheByAccount.put(identifiers.getAccountNumber(), identifiers);
        }
        return identifiers;
    }

    @Cacheable(value = "identifiers_cache_by_account_number", key = "#accountNumber")
    public Identifiers getIdentifiers(String accountNumber) {
        Identifiers identifiers = slowService.getIdentifiers();
        // ✅ 主动写入 customerId 缓存
        if (identifiers != null && identifiers.getCustomerId() != null) {
            cacheById.put(identifiers.getCustomerId(), identifiers);
        }
        return identifiers;
    }
}

? 注意:cacheManager.getCache("xxx") 返回 Cache 实例为线程安全对象,可安全复用。

⚠️ 关键注意事项

? 替代方案对比(不推荐用于本场景)

方案说明局限性
@CachePut 组合尝试用 @Cacheable 读 + @CachePut 写另一缓存Spring AOP 代理限制:同一 Bean 内部方法调用不触发 @CachePut,必须拆分为不同 Bean
自定义 CacheResolver动态决定写入哪些缓存无法区分「读操作」和「写操作」,易导致缓存污染
AOP 切面拦截在 @Cacheable 方法返回后统一写多缓存侵入性强、调试复杂,且难以精准捕获 key 和 result

✅ 总结

单次调用写入多缓存的本质,是在 Spring Cache 的声明式语义之上,补充命令式缓存操作。本文提供的 CacheManager 显式写入方案平衡了简洁性、可读性与可控性,适用于绝大多数中高并发业务场景。只要遵循「主缓存由 @Cacheable 管理,副缓存由代码显式维护」的原则,并做好键唯一性与失效一致性保障,即可高效支撑多维度快速检索需求。

本文转载于:互联网 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。