Начиная с версии 3.1, Spring Framework обеспечивает поддержку прозрачного добавления кэширования в существующее приложение Spring. Как и в случае поддержки транзакций, абстракция кэширования позволяет последовательно использовать различные решения для кэширования с минимальным воздействием на код.

В Spring Framework 4.1 абстракция кэша была значительно расширена за счет поддержки аннотаций JSR-107 и дополнительных возможностей настройки.

Основные сведения об абстракции кэша

Кэш и буфер

Термины "буфер" и "кэш" обычно используются как взаимозаменяемые. Обратите внимание, однако, что они представляют собой разные вещи. Традиционно буфер используется в качестве промежуточного временного хранилища данных между быстрым и медленным объектом. Поскольку одна сторона должна ждать другую (что влияет на производительность), буфер смягчает эту проблему, позволяя перемещать целые блоки данных сразу, а не небольшими частями. Данные записываются и считываются из буфера лишь один раз. Более того, буферы видны по крайней мере одной стороне, которая знает о них.

С другой стороны, кэш, по определению, является скрытым, и ни одна из сторон не знает, что происходит кэширование. Он также повышает производительность, но делает это за счет того, что позволяет быстро считывать одни и те же данные несколько раз.

По своей сути, абстракция кэша применяет кэширование к методам Java, тем самым уменьшая количество выполнений на основе информации, доступной в кэше. Таким образом, каждый раз, когда вызывается целевой метод, абстракция применяет логику кэширования, которая проверяет, вызывался ли уже ранее этот метод для заданных аргументов. Если вызывался, кэшированный результат возвращается без необходимости вызова фактического метода. Если метод не вызывался, то он вызывается, а результат кэшируется и возвращается пользователю, чтобы при следующем вызове метода был возвращен кэшированный результат. Таким образом, затратные с точки зрения ресурсов методы (будь то с интенсивными вычислениями на центральном процессоре или с интенсивным вводом-выводом) могут быть вызваны лишь единожды для заданного набора параметров, а результат повторно использован без необходимости повторного вызова метода. Логика кэширования применяется прозрачно, без какого-либо вмешательства в работу инициатора вызова.

Этот подход работает только для тех методов, которые гарантированно возвращают один и тот же вывод (результат) для данного ввода (или аргументов) независимо от того, сколько раз он вызывается.

Абстракция кэширования предусматривает и другие операции, связанные с кэшем, например, возможность обновлять содержимое кэша или удалять одну или все записи. Они полезны, если кэш работает с данными, которые могут меняться в процессе работы приложения.

Как и другие службы Spring Framework, служба кэширования является абстракцией (а не реализацией кэша) и требует использования реального хранилища для хранения данных кэша – то есть абстракция освобождает от необходимости писать логику кэширования, но не предоставляет реального хранилища данных. Эта абстракция воплощается интерфейсами org.springframework.cache.Cache и org.springframework.cache.CacheManager.

Spring предусматривает несколько реализаций этой абстракции: Кэши на основе java.util.concurrent.ConcurrentMap для JDK, Ehcache 2.x, кэш Gemfire, Caffeine и кэши, соответствующие стандарту JSR-107 (например, Ehcache 3.x).

Абстракция кэширования не предусматривает специальную обработку для многопоточных и многопроцессных окружений, так как такие функции обрабатываются реализацией кэша.

Если у вас многопроцессное окружение (то есть приложение развернуто на нескольких узлах), необходимо соответствующим образом сконфигурировать поставщика кэша. В зависимости от сценариев использования может хватить копии одних и тех же данных на нескольких узлах. Однако если данные изменяются в процессе работы приложения, то может понадобиться активировать другие механизмы распространения.

Кэширование конкретного элемента является прямым эквивалентом типичных блоков кода "get-if-not-found-then-proceed-and-put-eventually", встречающихся при программном взаимодействии с кэшем. Никакие блокировки не применяются, и несколько потоков могут одновременно пытаться загрузить один и тот же элемент. То же самое относится и к вытеснению. Если несколько потоков одновременно пытаются обновлять или вытеснять данные, то можно использовать устаревшие данные. Некоторые поставщики кэша предусматривают расширенные возможности в этой области. Более подробную информацию см. в документации поставщика кэша.

Чтобы использовать абстракцию кэша, необходимо позаботиться о двух аспектах:

  • Объявление кэширования: Определите методы, которые необходимо кэшировать, и их политику.

  • Конфигурация кэша: Резервный кэш, в котором хранятся данные и из которого они считываются.