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
相关产品推荐
相关产品推荐

