dev*_*123 6 spring spring-boot spring-cache caffeine-cache
是否可以将咖啡因CacheLoader::loadAll与@Cacheable带有集合参数的带注释方法一起使用,例如
@Cacheable(cacheNames = "exampleCache", cacheManager="exampleCacheManager", keyGenerator = "complexKeyGenerator")
List<String> getItems(List<String> keys, String commonForEveryKey) {
return ...
}
@Component
class ComplexKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
return ((List<String>)params[0]).stream()
.map(item -> new ComplexKey(item, (String) params[1]))
.collect(Collectors.toList());
}
}
@Data
@AllArgsConstructor
class ComplexKey {
String key;
String commonGuy;
}
class CustomCacheLoader implements CacheLoader<ComplexKey, String> {
@Override
public @Nullable String load(@NonNull ComplexKey key) throws Exception {
return loadAll(List.of(key)).get(key);
}
@Override
public @NonNull Map<@NonNull ComplexKey, @NonNull String> loadAll(@NonNull Iterable<? extends @NonNull ComplexKey> keys)
throws Exception {
return ...
}
}
@Bean
CacheManager exampleCacheManager(LoadingCache exampleCache) {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.registerCustomCache("exampleCache", exampleCache());
return cacheManager;
}
@Bean
Cache<Object, Object> exampleCache() {
return Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(1, TimeUnit.HOURS)
.recordStats()
.build(new CustomCacheLoader());
}
Run Code Online (Sandbox Code Playgroud)
看起来 Spring Cache 调用CustomCacheLoader::load而不是CustomCacheLoader::loadAll调用并失败ClassCastException,因为它无法将键集合转换为单个键。
我还应该配置什么才能使其正常工作?
不幸的是,Spring 不支持通过@Cacheable机制通过键集合检索缓存项的集合。
这是一个问题:https://github.com/spring-projects/spring-framework/issues/23221
实现此目的的一种选择是使用提供注释的自定义库( https://github.com/qaware/collection-cacheable-for-spring@CollectionCacheable ) :
@CollectionCacheable(cacheNames = "myCache")
Map<Long, MyEntity> findByIds(Collection<Long> ids) {
// do efficient batch retrieve of many MyEntity's and build result map
}
Run Code Online (Sandbox Code Playgroud)
如果您真的想坚持使用现有的代码,您可以将其概括为类似的内容:
@Component
class ComplexKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
if (params.length < 2 || !(params[0] instanceof Collection && params[1] instanceof String)) {
return SimpleKeyGenerator.generateKey(params);
}
return ((Collection<String>) params[0]).stream()
.map(item -> new ComplexKey(item, (String) params[1]))
.collect(Collectors.toList());
}
}
class CustomCacheLoader implements CacheLoader<Object, Object> {
@Override
public Object load(Object key) throws Exception {
final Collection<Object> keys = (key instanceof Collection) ?
((Collection<Object>) key) : Collections.singletonList(key);
final Collection<Object> values = new ArrayList<>(loadAll(keys).values());
return values;
}
@Override
public Map<Object, Object> loadAll(Iterable<?> keys) throws Exception {
...
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1270 次 |
| 最近记录: |