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

Spring @Cacheable注解unless表达式能否使用属性占位符?

在@Cacheable的unless表达式中引用属性占位符的解决方案

首先直接给结论:不能直接在@Cacheable的unless参数里使用${minCacheCalc}这种属性占位符语法,因为unless参数是SpEL(Spring表达式语言)表达式,Spring会优先解析SpEL,而${}是属性占位符的语法,在SpEL解析器里会被当成无效的表达式片段,这就是你遇到SpelParseException的原因。

不过我们有几种可行的替代方案来实现动态判断缓存的需求,下面一一说明:

方案1:在当前服务类中注入属性,通过SpEL引用该属性

你可以先把minCacheCalc属性注入到CalculationService中,然后在unless的SpEL里直接引用这个类的属性:

@Service
class CalculationService {
    // 注入配置文件中的minCacheCalc属性
    @Value("${minCacheCalc}")
    private Integer minCacheCalc;

    // 通过@calculationService引用当前bean的minCacheCalc属性
    @Cacheable(cacheNames="calculations", unless="#result < @calculationService.minCacheCalc")
    public Integer calculate(Integer i) {
        System.out.println("calculate(" + i + ")");
        return i * i - i;
    }
}

注意:@calculationService是Spring给当前bean生成的默认名称(类名首字母小写),如果你给bean指定了自定义名称,要替换成对应的名称。

方案2:通过SpEL引用Spring的Environment获取属性

Spring的Environment bean可以直接获取配置属性,我们可以在SpEL里直接调用它的方法:

@Service
class CalculationService {
    // 调用environment的getProperty方法,同时指定类型为Integer,避免字符串和数字比较的问题
    @Cacheable(cacheNames="calculations", unless="#result < @environment.getProperty('minCacheCalc', T(Integer).TYPE)")
    public Integer calculate(Integer i) {
        System.out.println("calculate(" + i + ")");
        return i * i - i;
    }
}

这里一定要指定类型转换,因为getProperty默认返回String,如果直接和#result(Integer类型)比较会抛出类型不匹配的异常。

方案3:使用@ConfigurationProperties绑定属性(适合多属性场景)

如果你的项目中有多个缓存相关的配置属性,推荐用@ConfigurationProperties来统一管理:

首先创建一个配置类:

@Component
@ConfigurationProperties(prefix = "") // 因为你的属性是minCacheCalc,没有前缀,所以prefix设为空
public class CacheConfigProperties {
    private Integer minCacheCalc;

    // 生成getter和setter方法
    public Integer getMinCacheCalc() {
        return minCacheCalc;
    }

    public void setMinCacheCalc(Integer minCacheCalc) {
        this.minCacheCalc = minCacheCalc;
    }
}

然后在服务类中引用这个配置类的属性:

@Service
class CalculationService {
    @Autowired
    private CacheConfigProperties cacheConfigProperties;

    @Cacheable(cacheNames="calculations", unless="#result < @cacheConfigProperties.minCacheCalc")
    public Integer calculate(Integer i) {
        System.out.println("calculate(" + i + ")");
        return i * i - i;
    }
}

这种方式更清晰,尤其当你有多个配置属性时,便于维护。

以上三种方案都能实现你想要的:当返回结果小于配置文件中minCacheCalc的值时,不进行缓存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:52:49