Какие существуют стратегии использования Spring Cache для методов, которые принимают параметр массива или коллекции?

Я хочу использовать абстракцию Spring Cache для аннотирования методов как @Cacheable. Однако некоторые методы предназначены для получения массива или набора параметров и возврата коллекции. Например, рассмотрите этот метод, чтобы найти энтиты:

public Collection<Entity> getEntities(Collection<Long> ids)

Семантически мне нужно кешировать Entity объекты индивидуально (с ключом по идентификатору), не основанные на совокупности идентификаторов в целом. Похоже на то, о чем этот вопрос.

Simple Spring Memcached поддерживает то, что я хочу, через его ReadThroughMultiCache, но я хочу использовать абстракцию Spring для поддержки простого изменения реализации хранилища кэша (Guava, Coherence, Hazelcast и т. д.), а не только memcached.

Какие существуют стратегии для кэширования такого метода с использованием Spring Cache?

1 ответ

Spring Cache Abstraction не поддерживает это поведение "из коробки". Однако это не значит, что это невозможно; это просто немного больше работы для поддержки желаемого поведения.

Я написал небольшой пример, демонстрирующий, как разработчик может достичь этого. В примере используется Springur ConcurrentMapCacheManager для демонстрации настроек. Этот пример необходимо будет адаптировать к нужному поставщику кэширования (например, Hazelcast, Coherence и т. Д.).

Короче говоря, вам нужно переопределить метод реализации CacheManager для "украшения" кэша. Это варьируется от реализации к реализации. в ConcurrentMapCacheManager, метод является createConcurrentMapCache (name: String). В Spring Data GemFire ​​вы должны переопределить метод getCache(name:String) для украшения возвращаемого кэша. Для Guava это будет createGuavaCache(name:String) в GuavaCacheManager, и так далее.

Тогда ваша индивидуально оформленная реализация Cache (возможно / в идеале, делегирующая фактическому значению Cache, из этого) будет обрабатывать кэширующие коллекции ключей и соответствующие значения.

Есть несколько ограничений этого подхода:

  1. Отсутствие кэша - это все или ничего; т.е. кешированные частичные ключи будут считаться пропущенными, если отсутствует какой-либо один ключ. Spring (OOTB) не позволяет одновременно возвращать значения кеша и вызывать метод для diff. Это потребует некоторых очень обширных изменений в Cache Abstraction, которые я бы не рекомендовал.

  2. Моя реализация является лишь примером, поэтому я решил не реализовывать операцию Cache.putIfAbsent(ключ, значение) ( здесь).

  3. Хотя моя реализация работает, ее можно сделать более надежной.

В любом случае, я надеюсь, что это даст некоторое представление о том, как правильно справиться с этой ситуацией.

Тестовый класс является автономным (использует Spring JavaConfig) и может работать без каких-либо дополнительных зависимостей (за исключением Spring, JUnit и JRE).

Ура!

Работал у меня. Вот ссылка на мой ответ. /questions/19524109/spring-cachejsr107-argument-listcollection-kak-chast-klyucha/55404654#55404654

TL:DR

@Cacheable(cacheNames = "test", key = "#p0")
public List<String> getTestFunction(List<String> someIds) {

Мой пример с String, но он также работает с Integer и Long и, возможно, с другими.

Другие вопросы по тегам