Рубрики
Без рубрики

Руководство по кэшированию весной

Как включить, настроить и эффективно использовать абстракцию кэширования весной.

Автор оригинала: Eugen Paraschiv.

1. Абстракция Кэша?

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

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

Дальнейшее чтение:

Пример Spring Boot Ehcache

Удаление кэша при весенней загрузке

2. Начало работы

Основная абстракция кэширования, предоставляемая Spring, находится в модуле spring-context . Поэтому при использовании Maven ваш pom.xml должен содержать следующую зависимость:


    org.springframework
    spring-context
    5.3.3

Интересно, что есть еще один модуль с именем spring-context-support , который находится поверх модуля spring-context и предоставляет еще несколько CacheManagers , поддерживаемых такими, как EhCache или Кофеин . Если мы хотим использовать их в качестве хранилища кэша, то вместо этого нам нужно использовать модуль spring-context-support :


    org.springframework
    spring-context-support
    5.3.3

Поскольку модуль spring-context-support транзитивно зависит от модуля spring-context , нет необходимости в отдельном объявлении зависимости для spring-context.

2.1. Пружинный Ботинок

Если мы используем Spring Boot, то мы можем использовать пакет spring-boot-starter-cache starter, чтобы легко добавить зависимости кэширования:


    org.springframework.boot
    spring-boot-starter-cache
    2.4.0

Под капотом стартер приносит модуль spring-context-support .

3. Включите Кэширование

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

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

@Configuration
@EnableCaching
public class CachingConfig {

    @Bean
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager("addresses");
    }
}

Мы, конечно, можем включить управление кэшем с помощью XML конфигурации, а также:


    

    
        
            
                
            
        
    

Примечание: После того, как мы включим кэширование, для минимальной настройки мы должны зарегистрировать диспетчер кэша .

3.1. Использование Пружинного Ботинка

При использовании Spring Boot простое присутствие стартового пакета на пути к классу рядом с аннотацией EnableCaching зарегистрировало бы тот же ConcurrentMapCacheManager. Таким образом, нет необходимости в отдельном объявлении компонента.

Кроме того, мы можем настроить автоматически настроенный CacheManager с помощью одного или нескольких Cache Manager Customized beans:

@Component
public class SimpleCacheCustomizer 
  implements CacheManagerCustomizer {

    @Override
    public void customize(ConcurrentMapCacheManager cacheManager) {
        cacheManager.setCacheNames(asList("users", "transactions"));
    }
}

Автоконфигурация кэша | автоконфигурация подбирает эти настройки и применяет их к текущему CacheManager до его полной инициализации.

4. Используйте Кэширование С Аннотациями

После того, как мы включили кэширование, следующим шагом является привязка поведения кэширования к методам с декларативными аннотациями.

4.1. @Cacheable

Самый простой способ включить поведение кэширования для метода-это разграничить его с помощью @Cacheable и параметризовать его именем кэша , в котором будут храниться результаты:

@Cacheable("addresses")
public String getAddress(Customer customer) {...}

Вызов getAddress() сначала проверит кэш адреса перед фактическим вызовом метода, а затем кэширует результат.

Хотя в большинстве случаев достаточно одного кэша, платформа Spring также поддерживает несколько кэшей, передаваемых в качестве параметров:

@Cacheable({"addresses", "directory"})
public String getAddress(Customer customer) {...}

В этом случае, если какой-либо из кэшей содержит требуемый результат, результат возвращается и метод не вызывается.

4.2. @CacheEvict

Теперь, в чем будет проблема с созданием всех методов @Cacheable ?

Проблема в размере. W e не хочет заполнять кэш значениями, которые нам не нужны часто . Кэши могут расти довольно большими, довольно быстро, и мы можем хранить много устаревших или неиспользуемых данных.

Мы можем использовать аннотацию @CacheEvict , чтобы указать удаление одного или нескольких/всех значений, чтобы новые значения можно было снова загрузить в кэш:

@CacheEvict(value="addresses", allEntries=true)
public String getAddress(Customer customer) {...}

Здесь мы используем дополнительный параметр все записи в сочетании с очищаемым кэшем; это очистит все записи в кэше адреса и подготовит его к новым данным.

4.3. @CachePut

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

Вместо этого мы выборочно обновляем записи всякий раз, когда мы их изменяем.

С помощью аннотации @CachePut мы можем обновить содержимое кэша, не вмешиваясь в выполнение метода. То есть метод всегда будет выполняться, а результат кэшироваться:

@CachePut(value="addresses")
public String getAddress(Customer customer) {...}

Разница между @Cacheable и @CachePut заключается в том , что @Cacheable будет пропускать запуск метода , тогда как @CachePut будет фактически запускать метод , а затем помещать его результаты в кэш.

4.4. Кэширование @

Что делать, если мы хотим использовать несколько аннотаций одного и того же типа для кэширования метода? Давайте рассмотрим неправильный пример:

@CacheEvict("addresses")
@CacheEvict(value="directory", key=customer.name)
public String getAddress(Customer customer) {...}

Приведенный выше код не будет скомпилирован, так как Java не позволяет объявлять несколько аннотаций одного и того же типа для данного метода.

Обходным путем для решения вышеуказанной проблемы было бы:

@Caching(evict = { 
  @CacheEvict("addresses"), 
  @CacheEvict(value="directory", key="#customer.name") })
public String getAddress(Customer customer) {...}

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

4.5. @CacheConfig

С помощью аннотации @CacheConfig мы можем упорядочить некоторые конфигурации кэша в одном месте на уровне класса, чтобы нам не приходилось объявлять вещи несколько раз:

@CacheConfig(cacheNames={"addresses"})
public class CustomerDataService {

    @Cacheable
    public String getAddress(Customer customer) {...}

5. Условное Кэширование

Иногда кэширование может не работать хорошо для метода во всех ситуациях.

Сокращая наш пример из аннотации @CachePut , это приведет как к выполнению метода, так и к кэшированию результатов каждый раз:

@CachePut(value="addresses")
public String getAddress(Customer customer) {...}

5.1. Параметр Состояния

Если мы хотим получить больший контроль над активностью аннотации, мы можем параметризовать @CachePut параметром условия, который принимает выражение SpEL и гарантирует, что результаты будут кэшироваться на основе оценки этого выражения:

@CachePut(value="addresses", condition="#customer.name=='Tom'")
public String getAddress(Customer customer) {...}

5.2. Если Параметр

Мы также можем управлять кэшированием на основе вывода метода, а не ввода с помощью параметра если только :

@CachePut(value="addresses", unless="#result.length()<64")
public String getAddress(Customer customer) {...}

Приведенная выше аннотация будет кэшировать адреса, если они не будут короче 64 символов.

Важно знать, что параметры condition и , если только не могут использоваться в сочетании со всеми аннотациями кэширования.

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

6. Декларативное кэширование на основе XML

Если у нас нет доступа к исходному коду нашего приложения или мы хотим внедрить поведение кэширования извне, мы также можем использовать декларативное кэширование на основе XML.

Вот наша конфигурация XML: