Spring 缓存以通过 cacheName 配置禁用缓存

Spring Cache to Disable Cache by cacheName configuration

我正在使用 spring 启动,将 spring 缓存与其他缓存组件集成非常容易。

通过缓存数据,我们可以使用@Cachable注解,但是仍然需要配置并在cacheManager中添加cacheName,如果没有这一步,访问方法会出现异常:

java.lang.IllegalArgumentException: Cannot find cache named 'xxxx' for Builder

我的问题是,如果我们不配置 cacheName,是否能够禁用缓存而不是引发错误?我提出这个问题是因为 spring 缓存在 CacheProperties 中提供了一个配置 spring.cache.cacheNames

不确定 @Cachable 中的 condition 属性是否适用于此。

任何想法都非常感谢!!提前致谢!

这真的取决于你的 "caching provider" 和 CacheManager interface, in particular. Since Spring's Cache Abstraction is just that, an "abstraction" it allows you to plugin different providers and backend data stores to support the caches required by your application (i.e. as determined by Spring's caching annotations, or alternatively, the JSR-107-JCache annotations; see here 的执行情况)。

例如,如果您要使用 Spring 提供的框架 ConcurrentMapCacheManager implementation (not recommended for production except for really simple UCs), then if you choose to not declare your caches at configuration/initialization time (using the default, no-arg constructor) then the "Caches" are lazily created. However, if you do declare your "Caches" at configuration/initialization time (using the constructor accepting cache name arguments), then if your application uses a cache (e.g. @Cacheable("NonExistingCache")) not explicitly declared, then Exception would be thrown because the getCache(name:String):Cache method would return null and the CacheInterceptor initialization logic would throw an IllegalArgumentException for no Cache available for the caching operation (follow from the CacheIntercepter down, here, here, here, here and then here)。

目前无法为不存在的缓存禁用此初始化检查(即抛出异常)。你能做的最好的事情就是像 ConcurrentMapCacheManager 实现一样,延迟创建 Caches。但是,这在很大程度上取决于您的缓存提供程序实现。显然,一些缓存提供程序比其他的更复杂,动态创建 Cache(即懒惰地)可能更昂贵且成本更高,因此缓存提供程序不支持或不推荐。

不过,您可以通过包装任何 CacheManager 实现(您选择的)来解决此限制,并委托给 "existing" Caches 和 [=69= 的底层实现] 通过提供核心 Spring CacheManagerCache 接口的一些简单包装器实现,将其视为缓存未命中来处理 "non-existing" Caches

这是一个 example integration test class that demonstrates your current problem. Note the test/assertions 用于不存在的 Caches

然后,这里有一个 example integration test class that demonstrates how to effectively disable caching for non-existing Caches (not provided by the caching provider). Once again, note the test/assertions 用于安全访问不存在的 Caches

这是通过 Spring Cache 接口的 wrapper delegate for CacheManager (which wraps and delegates to an existing caching provider, which in this case is just the ConcurrentMapCacheManager again (see here), but would work for any caching provider supported by Spring Cache Abstraction) along with the NoOpNamedCache implementation 实现的。这个无操作 Cache 实例可以是一个 Singleton 并且如果您不关心名称,则可重复用于所有不存在的 Caches。但是,它会给你一定程度的可见性 "named" Caches 没有配置实际的 Cache 因为这很可能会对你的服务产生影响(即没有缓存的服务方法启用,因为 "named" 缓存不存在)。

无论如何,这可能不是您真正想要的,如果您将其投入生产,我什至会提醒您要特别小心,因为(我认为)它确实应该很快失败,因为缺少 Caches,但这确实实现了你想要的。

显然,它是可配置的,您可以根据缓存名称或其他条件使其成为有条件的,因为如果您真的不关心或不想在某些上下文中缓存某些服务方法,那么它由您决定,这种方法非常灵活,如果需要,您可以完全选择。

希望这能给你一些想法。