我有一个服务,它调用外部系统通过其外部id检索某种对象,并将它们提交回更新。而不是逐个检索对象,有一个更通用的目的方法:
public interface ExternalSystem {
List<ExternalDTO> getObjects(List<String> externalIds);
void updateObjects(List<ExternalDTO> updates);
}
我想在ExternalSystem调用之上放置一个缓存,因为它们非常昂贵。
在服务的实现中,我可以简单地使用spring注释:
@Cacheable("cache-external")
List<ExternalDTO> getObjects(List<String> externalIds) {}
@CacheEvict(cacheNames="cache-external", allEntries=true)
void updateObjects(List<ExternalDTO> updates);
但是,如果我在externalIds之间有很多交集,那么这样的缓存会表现得非常糟糕,即
所以,问题是如何实现自定义策略(我认为它不是开箱即用的),这将只驱逐那些真正应该被驱逐的条目,并使密钥成为一种方式从缓存中检索交叉对象?
更新。我发现了两个类似的问题:
UPD2。 这是类似于我想要的东西,除了我将为集合中的每个项目放入String和ExternalDTO的缓存对。 element-level-caching-of-list-to-list
答案 0 :(得分:0)
AFAIK使用注释无法做到这一点。您可以使用命令式API,其中包含您需要的批量操作,例如Cache.getAll(keySet)
和Cache.removeAll(keySet)
答案 1 :(得分:0)
对我来说,此配置可以正常工作。 这是我的代码的混淆版本。
@Cacheable(cacheNames = "test", key = "#p0")
public List<String> getTestFunction(List<String> someIds) {
getTestFunction(Arrays.asList("A","B","C"));
2020-04-02 15:12:35.492 TRACE 18040 --- [Test worker] o.s.cache.interceptor.CacheInterceptor : Computed cache key '[A, B, C]' for operation Builder[public java.util.List org.Main.getTestFunction(java.util.List)] caches=[test] | key='#p0' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='' | sync='false'
您看到它隐含了字符串
... Computed cache key '[A, B, C]' ...
我的设置: /resources/ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<cache name="test"
maxBytesLocalHeap="1M"
timeToLiveSeconds="300"/>
</ehcache>
gradle.build
plugins {
id "org.springframework.boot" version "2.2.4.RELEASE"
....
}
dependencies {
implementation "org.springframework.boot:spring-boot-starter-cache"
implementation "org.ehcache:ehcache:3.8.1"
...
}