Статьи

Spring Caching и Google Guava Cache

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

Моя цель здесь состоит в том, чтобы охватить одну из более новых реализаций кэша, которые Spring теперь предоставляет с версией 4.0+ фреймворка — используя Google Guava Cache.

Вкратце рассмотрим сервис, который имеет несколько медленных методов:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
public class DummyBookService implements BookService {
 
 @Override
 public Book loadBook(String isbn) {
  // Slow method 1.
 
 }
 
 @Override
 public List<Book> loadBookByAuthor(String author) {
  // Slow method 2
 }
 
}

С помощью абстракции Spring Caching повторяющиеся вызовы с одним и тем же параметром могут быть ускорены аннотацией метода по этим линиям — здесь результат loadBook кэшируется в «книжный» кеш, а список книг, помещенных в другую «книгу» кэш:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
public class DummyBookService implements BookService {
 
 @Override
 @Cacheable("book")
 public Book loadBook(String isbn) {
  // slow response time..
 
 }
 
 @Override
 @Cacheable("books")
 public List<Book> loadBookByAuthor(String author) {
  // Slow listing
 }
}

Теперь для поддержки абстракции кэширования требуется наличие CacheManager, который отвечает за управление базовыми кешами для хранения кэшированных результатов. С новой поддержкой Guache Cache CacheManager имеет следующие черты:

1
2
3
4
@Bean
public CacheManager cacheManager() {
 return new GuavaCacheManager("books", "book");
}

Google Guava Cache предоставляет богатый API для предварительной загрузки кеша, установки продолжительности вытеснения на основе последнего доступа или времени создания, установки размера кеша и т. Д. Если кеш настраивается, то можно передать guava CacheBuilder в CacheManager для этой настройки:

1
2
3
4
5
6
@Bean
public CacheManager cacheManager() {
 GuavaCacheManager guavaCacheManager =  new GuavaCacheManager();
 guavaCacheManager.setCacheBuilder(CacheBuilder.newBuilder().expireAfterAccess(30, TimeUnit.MINUTES));
 return guavaCacheManager;
}

Это хорошо работает, если все кэши имеют одинаковую конфигурацию, что, если кэши нужно настроить по-разному — например в приведенном выше примере я могу захотеть, чтобы кэш «книги» никогда не истекал, но кэш «книг» имеет срок действия 30 минут, тогда абстракция GuavaCacheManager не работает должным образом, вместо этого на самом деле лучшим решением является использование SimpleCacheManager, который обеспечивает более прямой доступ к кешу и может быть настроен следующим образом:

01
02
03
04
05
06
07
08
09
10
@Bean
public CacheManager cacheManager() {
 SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
 GuavaCache cache1 = new GuavaCache("book", CacheBuilder.newBuilder().build());
 GuavaCache cache2 = new GuavaCache("books", CacheBuilder.newBuilder()
             .expireAfterAccess(30, TimeUnit.MINUTES)
             .build());
 simpleCacheManager.setCaches(Arrays.asList(cache1, cache2));
 return simpleCacheManager;
}

Этот подход работает очень хорошо, если требуется, чтобы определенные кэши могли быть сконфигурированы для поддержки самими различными механизмами кэширования, скажем, простой хэш-картой, некоторые с помощью Guava или EhCache, некоторые с помощью распределенных кэшей, таких как Gemfire.

Ссылка: Spring Caching абстракция и Google Guava Cache от нашего партнера по JCG Биджу Кунджуммен в блоге all and sundry.