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

Spring Cache中用方法返回值设缓存键遇EL1007E异常的解决

问题根源:@Cacheable的执行顺序限制

你遇到的问题本质是Spring Cache注解的执行时机差异:

  • @Cacheable的key属性是在方法执行前解析的——Spring需要先根据key判断缓存里有没有对应数据,决定要不要执行方法。这时候方法还没运行,#result自然是null,所以访问#result.name就会抛出找不到属性的异常。
  • 而unless属性是在方法执行完成后才会解析的——这时候方法已经返回了结果,#result指向实际的Person对象,所以能正常访问它的name属性。
解决方案:根据需求选择合适的缓存方式

1. 每次执行方法后用返回值name更新缓存

可以改用@CachePut注解,它的逻辑是先执行方法,再用方法结果生成key并存入缓存,这时候#result已经存在,能正常用于key的生成:

@CachePut(value = "Cache", key = "#result.name", unless="#result.name == 'Foo'")
public Person getById(String id){
    // 你的数据库查询逻辑
}

注意:@CachePut不会检查缓存,每次调用都会执行方法,适合需要确保缓存与数据源同步的场景。

2. 先通过name查询缓存,不存在再执行方法

如果业务允许,把方法参数改为name,直接用@Cacheable即可:

@Cacheable(value = "Cache", key = "#name", unless="#result.name == 'Foo'")
public Person getByName(String name){
    // 根据name查询数据库的逻辑
}

如果必须通过id查询,可以在getById方法中先查数据库得到Person,再调用getByName来复用缓存逻辑。

3. 手动控制缓存(最灵活)

如果以上注解方式不符合业务逻辑,直接用CacheManager手动操作缓存,完全掌握缓存时机和key生成:

@Autowired
private CacheManager cacheManager;

public Person getById(String id){
    // 从数据库查询Person
    Person person = yourPersonRepository.findById(id).orElse(null);
    
    if(person != null && !"Foo".equals(person.getName())){
        // 获取指定缓存
        Cache cache = cacheManager.getCache("Cache");
        // 以name为key存入缓存
        cache.put(person.getName(), person);
    }
    
    return person;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:52:52