如何通过SpEL实现@CacheEvict动态配置多缓存名称?
场景设置
以下为配置内容:
application.properties
Property.cache = name1,name2,...,nameN
CacheManager.java
[...] @Scheduler(time_of_schedule) @CacheEvict(value="#{'${property.cache}.split()'}") void dueCache(){ log.info("cache clean"); } [...]
问题描述
使用@CacheEvict的value属性时抛出异常:
nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'property.cache'.split(',')' in value "#{'${property.cache'.split(',')}"
核心问题:@CacheEvict的value类型为String[],直接用SpEL拆分配置字符串的写法无法适配该类型,同时存在配置键大小写不匹配的问题(配置为Property.cache,代码中写的是property.cache)。需找到通过SpEL从配置文件读取缓存名称列表并注入String[]类型value的可行方案。
已尝试方案
@CacheEvict(value = "#{'${property.cache}'.split(',')}", allEntries = true):仅在value为String类型时可行,适配String[]时出错@CacheEvict(value = "#{T(java.util.Arrays).asList(#root.getProperty('property.cache').split(','))}", allEntries = true):同样仅适配String类型value@CacheEvict(value = {"cache1","cache2"}, allEntries = true):手动枚举可正常运行,但扩展性差@CacheEvict(value = "cache1", allEntries = true):单缓存名称可行,但无法批量处理
解决方案
方法1:类内注入数组后通过SpEL引用
先在类中用@Value将配置值注入为String[],再在@CacheEvict的SpEL中直接引用该数组:
@Component public class CacheManager { // 注意配置键大小写与文件保持一致 @Value("${Property.cache}") private String[] cacheNames; @Scheduler(time_of_schedule) @CacheEvict(value = "#{cacheNames}", allEntries = true) void dueCache() { log.info("cache clean"); } }
原理:SpEL可直接引用当前Bean的成员属性,cacheNames本身就是String[]类型,完美匹配@CacheEvict的value参数要求。
方法2:Spring Boot配置类绑定
适合Spring Boot项目,通过配置类统一管理缓存配置:
- 创建配置类绑定配置值:
@ConfigurationProperties(prefix = "property") public class CacheProperties { private String[] cache; // getter、setter public String[] getCache() { return cache; } public void setCache(String[] cache) { this.cache = cache; } }
- 在启动类或配置类上启用配置绑定:
@SpringBootApplication @EnableConfigurationProperties(CacheProperties.class) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
- 在缓存清理方法中通过SpEL引用配置类的属性:
@Component public class CacheManager { private final CacheProperties cacheProperties; // 构造注入配置类 public CacheManager(CacheProperties cacheProperties) { this.cacheProperties = cacheProperties; } @Scheduler(time_of_schedule) @CacheEvict(value = "#{cacheProperties.cache}", allEntries = true) void dueCache() { log.info("cache clean"); } }
优势:符合Spring Boot配置规范,便于扩展更多缓存相关配置。
方法3:修正SpEL写法直接转换数组
若不想额外注入属性,可修正SpEL的写法(注意配置键大小写一致):
@Scheduler(time_of_schedule) @CacheEvict(value = "#{'${Property.cache}'.split(',')}", allEntries = true) void dueCache() { log.info("cache clean"); }
注意:部分旧版本Spring可能存在SpEL返回数组无法直接适配@CacheEvict的String[]参数的问题,若出现此情况优先使用前两种方法。同时需确保配置文件中Property.cache的格式正确,无多余空格。
内容的提问来源于stack exchange,提问作者Massirito
相关产品推荐
相关产品推荐

