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

Spring Boot升级后@CachePut注解部分方法未执行数据更新

问题:Spring Boot 3.2.3 中@CachePut部分缓存无法触发数据查询逻辑

将应用从Spring Boot 1.2.6升级至3.2.3后,使用Spring Cache + Ehcache框架时出现异常:标注@CachePut的方法中,仅HANDLERLISTMAP缓存对应的方法能正常执行数据查询并刷新缓存,而USERS、HANDLERBETRIEBLISTMAP对应的方法,即使提前调用缓存清除逻辑,数据查询代码也未执行。

异常代码示例

未执行查询的方法(USERS缓存)

@CachePut(value = CacheDefinitions.USERS)
@Override
public Map<String, User> refreshUsers() {
    try {
        dataFileStore.clearCache(CacheDefinitions.USERS);
        return mappingDataRepository.getUsers().get(); // getUsers()未执行
    } catch (InterruptedException | ExecutionException ex) {
        throw new RuntimeException(ex);
    }
}

未执行查询的方法(HANDLERBETRIEBLISTMAP缓存)

@CachePut(value = CacheDefinitions.HANDLERBETRIEBLISTMAP)
@Override
public Map<String, List<String>> refreshHandlerBetriebListMap() {
    try {
        dataFileStore.clearCache(CacheDefinitions.HANDLERBETRIEBLISTMAP);
        return mappingDataRepository.getHandlerBetriebListMap().get(); // 未执行
    } catch (InterruptedException | ExecutionException ex) {
        throw new RuntimeException(ex);
    }
}

曾正常执行、后续失效的方法(HANDLERLISTMAP缓存)

@CachePut(value = CacheDefinitions.HANDLERLISTMAP)
@Override
public Map<String, ListAccessLists> refreshHanderListMap(){
    dataFileStore.clearCache(CacheDefinitions.HANDLERLISTMAP);
    return proxy.getHandlerListMap(); // 未执行
}

正常执行的方法(HANDLERLISTMAP缓存)

@CachePut(value = CacheDefinitions.HANDLERLISTMAP)
@Override
public Map<String, ListAccessLists> refreshHanderListMap(){
    dataFileStore.clearCache(CacheDefinitions.HANDLERLISTMAP);
    return proxy.getHandlerListMap(); // 此方法正常执行
}

可能原因及解决步骤

1. 移除冗余的手动缓存清除操作

@CachePut的核心语义是强制执行方法逻辑,再将返回值更新到缓存,无需手动调用清除缓存。Spring Boot 3.x对应的Spring Framework 6.x中,缓存拦截器的执行顺序与1.x存在差异,手动清除缓存可能与Spring Cache的内置逻辑冲突,导致方法执行被意外拦截。

直接删除dataFileStore.clearCache(...)调用,重新测试方法是否执行查询逻辑。

2. 检查异步查询的Future复用问题

未执行查询的方法均依赖mappingDataRepository返回的Future对象调用get(),如果该Repository内部对Future实例做了缓存复用,会导致get()直接返回旧结果,不会触发新的查询。

  • 检查mappingDataRepository的实现,确保每次调用getUsers()、getHandlerBetriebListMap()时,都会创建新的异步查询任务,而非复用已完成的Future实例。
  • 可临时替换为同步查询逻辑,验证是否能正常触发数据查询。

3. 校验缓存名称的配置合法性

Spring Boot 3.x对缓存配置的校验更严格,若CacheDefinitions中定义的缓存名称未在Ehcache配置文件(如ehcache.xml或application.yml)中正确声明,可能导致缓存逻辑异常。

  • 确认USERS、HANDLERBETRIEBLISTMAP等缓存名称在Ehcache配置中存在,示例配置:
    <!-- ehcache.xml -->
    <cache alias="USERS">
      <expiry>
        <ttl unit="seconds">3600</ttl>
      </expiry>
      <heap>1000</heap>
    </cache>
    <cache alias="HANDLERBETRIEBLISTMAP">
      <expiry>
        <ttl unit="seconds">3600</ttl>
      </expiry>
      <heap>1000</heap>
    </cache>
    
  • 检查缓存名称是否存在拼写错误(如方法名refreshHanderListMap中的Hander应为Handler,可能导致缓存名称匹配异常)。

4. 验证Spring AOP代理有效性

Spring Cache基于AOP实现,若方法调用未通过Spring代理对象(如内部调用this.refreshUsers()),会导致@CachePut注解失效,方法逻辑可能被跳过。

  • 确保所有@CachePut方法的调用是通过Spring容器管理的Bean实例触发,而非直接调用类内部方法。
  • 可通过打印this.getClass().getName()确认当前对象是否为Spring代理类(类名包含$Proxy或CGLIB标识)。

5. 开启调试日志定位问题

开启Spring Cache和Ehcache的调试日志,查看缓存操作的详细流程,确认@CachePut是否触发方法执行、缓存更新是否正常:

# application.yml
logging:
  level:
    org.springframework.cache: DEBUG
    org.ehcache: DEBUG

通过日志可明确:

  • @CachePut拦截器是否生效
  • 方法执行前/后的缓存操作细节
  • 是否存在缓存名称匹配错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 23:23:20