You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring缓存工作原理及@Cacheable感知数据库变更问询

Spring缓存相关问题解答

1. Spring缓存的工作机制是什么?

Spring Cache 是基于 AOP 实现的一套缓存抽象层,核心工作流程可以拆解为以下几步:

  • 方法拦截:被缓存注解(如@Cacheable)标记的方法,会被 Spring 的缓存切面拦截。
  • 缓存检查:方法执行前,先根据指定的缓存名称和键,检查缓存中是否存在对应的结果:
    • 如果缓存命中,直接返回缓存中的数据,跳过方法体执行;
    • 如果缓存未命中,执行原始方法获取结果,再将结果存入指定缓存,供后续调用复用。
  • 多缓存支持:它通过CacheManager接口适配多种缓存实现(如 EhCache、Caffeine、Redis 等),开发者无需改动业务代码就能切换缓存提供者。
  • 核心操作注解:除了@Cacheable,还有@CacheEvict(清除缓存)、@CachePut(更新缓存)、@Caching(组合多个缓存操作)来覆盖不同的缓存场景。

2. @Cacheable注解如何感知数据库中的数据变更?

@Cacheable本身不会自动感知数据库的数据变更——它只负责读取和写入缓存,并不会主动监听数据库的变化。如果数据库数据更新后不处理缓存,就会出现缓存与数据不一致的问题。下面是几种常用的解决方案:

方案1:用@CacheEvict主动清除缓存

在修改、删除数据的业务方法上添加@CacheEvict,当这些方法执行时,自动清除对应缓存:

// 保存/更新员工时,清除整个employee缓存(因为getAllEmployees的结果是全量数据)
@CacheEvict(value = "employee", allEntries = true)
public Employee saveEmployee(Employee employee) {
    return employeeRepository.save(employee);
}

// 删除单个员工时,清除对应id的缓存项
@CacheEvict(value = "employee", key = "#id")
public void deleteEmployee(Long id) {
    employeeRepository.deleteById(id);
}

如果你的getAllEmployees方法是用固定键缓存的(比如key = "#root.methodName"),也可以直接指定该键进行清除,而不用清空整个缓存。

方案2:用@CachePut实时更新缓存

如果修改数据后需要直接将新结果写入缓存(而不是清除),可以用@CachePut——它会先执行方法体,再把新结果覆盖到缓存中:

@CachePut(value = "employee", key = "#employee.id")
public Employee updateEmployee(Employee employee) {
    return employeeRepository.save(employee);
}

方案3:监听数据库事件触发缓存操作

如果使用 JPA,可以监听实体的生命周期事件(如PostUpdate、PostPersist、PostRemove),在事件触发时手动操作缓存:

@Component
public class EmployeeCacheListener {
    private final CacheManager cacheManager;

    public EmployeeCacheListener(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }

    @EventListener
    public void handleEmployeeChange(AbstractEntityEvent event) {
        if (event.getEntity() instanceof Employee) {
            Cache cache = cacheManager.getCache("employee");
            if (cache != null) {
                cache.clear(); // 或根据实体ID清除单个缓存项
            }
        }
    }
}

方案4:设置缓存过期时间(TTL)

如果业务允许短时间的数据不一致,可以给缓存设置过期时间。当缓存到期后自动失效,下次调用方法时会重新从数据库拉取最新数据。比如在 Redis 或 Caffeine 的配置中设置expireAfterWrite参数。

内容的提问来源于stack exchange,提问作者Geek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:29:28