为何配置@ConditionalOnProperty后Bean无视matchIfMissing值始终被创建
问题根因
你当前的@ConditionalOnProperty注解配置逻辑不完整,导致条件始终匹配:@ConditionalOnProperty默认的匹配规则是:只要指定的属性存在、且属性值不为字符串false,就会判定条件成立。你额外设置了matchIfMissing = true,相当于补充了「属性不存在时也判定条件成立」的逻辑,最终就变成了:不管有没有配置spring.cache.type、不管配置的值是什么,条件都成立,所以你的自定义Bean永远会被创建。
解决方案
根据你的实际需求选择对应配置即可:
场景1:仅当spring.cache.type完全未配置时才创建自定义Bean
如果你用的是Spring Boot 2.4及以上版本,直接用专门的缺失属性条件注解更简洁:
@Bean @ConditionalOnMissingProperty(name = "spring.cache.type") public CacheManager cacheManager() { ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager() { @Override protected Cache createConcurrentMapCache(final String name) { return new ConcurrentMapCache(name, CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.SECONDS).build().asMap(), false); } }; return cacheManager; }
如果是低版本Spring Boot,可以调整@ConditionalOnProperty的配置,指定只匹配空值:
@Bean @ConditionalOnProperty(name = "spring.cache.type", havingValue = "", matchIfMissing = true) public CacheManager cacheManager() { // 原有实现逻辑 }
场景2:仅当容器中不存在其他CacheManager Bean时才创建自定义Bean
如果你的核心需求是「优先使用用户配置的其他缓存管理器(比如Redis缓存管理器),没有其他实现时才用自定义的ConcurrentMap实现」,更推荐用Bean缺失条件注解,和Spring Boot缓存自动配置的逻辑对齐:
@Bean @ConditionalOnMissingBean(CacheManager.class) public CacheManager cacheManager() { // 原有实现逻辑 }
这种写法兼容所有配置场景,只要用户通过配置spring.cache.type=redis等方式触发了其他缓存管理器的自动创建,你的自定义Bean就不会被注册。
场景3:仅当缓存类型为默认simple类型时替换原生实现
如果你需要和Spring Boot原生缓存逻辑对齐,只有当缓存类型为默认的simple(ConcurrentMap缓存)时才替换默认实现,可以这么写:
@Bean @ConditionalOnProperty(name = "spring.cache.type", havingValue = "simple", matchIfMissing = true) public CacheManager cacheManager() { // 原有实现逻辑 }
这样只要用户配置了其他type(比如redis、caffeine等),这个Bean就不会被创建,完全符合Spring Boot的自动配置优先级。
内容的提问来源于stack exchange,提问作者stackMan10

