Какие существуют стратегии использования 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, из этого) будет обрабатывать кэширующие коллекции ключей и соответствующие значения.
Есть несколько ограничений этого подхода:
Отсутствие кэша - это все или ничего; т.е. кешированные частичные ключи будут считаться пропущенными, если отсутствует какой-либо один ключ. Spring (OOTB) не позволяет одновременно возвращать значения кеша и вызывать метод для diff. Это потребует некоторых очень обширных изменений в Cache Abstraction, которые я бы не рекомендовал.
Моя реализация является лишь примером, поэтому я решил не реализовывать операцию Cache.putIfAbsent(ключ, значение) ( здесь).
Хотя моя реализация работает, ее можно сделать более надежной.
В любом случае, я надеюсь, что это даст некоторое представление о том, как правильно справиться с этой ситуацией.
Тестовый класс является автономным (использует 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 и, возможно, с другими.