Дальнейшие усовершенствования кеширования в Spring 4.1

Дополню свою более раннюю статью про JSR-107. Хочется обратить внимание читателей на новые возможности, которые открыли нам добавление поддержки JCache, показав способ подружить их с теми приёмами и подходами программирования, что были доступны до этого. Стоит упомянуть так же о том, что в Spring 4.1 были добавлены некоторые улучшения, описанные разработчиками.

Я рад сообщить, что новые учебные материалы, посвященные кешированию, были опубликованы в Кеширование данных с Spring!

CacheResolver

Одна из самых хороших возможностей, найденная в JSR-107, была в разрешении кеширования в процессе работы, которая основана на фактическом выполнении метода. До сих пор мы поддерживали имя(имена) кеша на уровне определения в аннотации. Было несколько отчетов о проблеме, когда использовалось белее одного CacheManager, необходимо было разрешить конфликт, какому менеджеру использовать какое имя.

В конечном итоге мы сделали подобие CacheResolver абстракции, чтобы предоставить гибкость в настройках. Как вы можете подозревать, реализация по умолчанию берет CacheManager и разрешает кеш(и) на основе предоставленных именах. Т.к. имена больше не требуются, Spring 4.1 позволяет писать следующее:

@Cacheable
public Book findBook(ISBN isbn) {...}

Конечно, вы можете определить собственный CacheResolver, который знает, что делать для каждого конкретного вызова или если вам нужно обеспечить кеширование другим способом.

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

Настройки на уровне операций

Сообществом было высказано пожелание иметь возможность управлять поведением кеша на много более глубоком уровне. Spring 4.1 позволяет определить CacheResolver (или CacheManager) и KeyGenerator в каждой операции.

К примеру, ниже применяется собственный KeyGenerator к конкретной операции

@Cacheable(value="book", keyGenerator="myKeyGenerator")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

Это выглядит как KeyGenerator бин с именем myKeyGenerator. CacheManager и CacheResolver могут быть установлены аналогичным образом.

Настройки на уровне класса

Другое пожелание сообщества состояло в совместной использовании настроек на уровне метода, но без включение в поведение кеширования по умолчанию. Знакомьтесь, @CacheConfig, который обеспечивает те же настройки на уровне класса, т.е. имена кеша, CacheResolver (или CacheManager) и KeyGenerator.

@CacheConfig(cacheNames="book", keyGenerator="myKeyGenerator") 
public class BookRepository {

    @Cacheable
    public Book findBook(ISBN isbn) {...}

    public Book thisIsNotCached(String someArg) {...}
}

JCache интеграция

Одной из главных целей при реализации поддержки JSR-107 было использование того, что у нас уже было в нашей собственной абстракции, чтобы переход приложений был как можно плавнее. Поддержка JCache фактически использует внутреннюю Spring абстракцию кеширования, которая позволяет вам повторно использовать существующую инфраструктуру кеширования со стандартными аннотациями. Когда вы определяете JSR-107 компонент, такой как javax.cache.annotation.CacheResolver или javax.cache.annotation.CacheKeyGenerator, мы перенаправляем его через нашу абстракцию с помощью адаптера.

Фактически, это означает, что вы можете сохранить свою существующую инфраструктуру, какой бы ни был выбран механизм. К примеру, у вас может быть ConcurrentMapCacheManager, который использует ConcurrentHashMap со стандартными JSR-107 аннотациями.

Если хотите попробовать, то можете обратиться к этому руководству, которое использует JCache вместо Spring аннотаций(коммит 32fea97 отображает, что на самом деле изменилось).

Итоги

Spring 4.1 выйдет этим летом и обеспечит значительным улучшением абстракции кеширования; добавление поддержки JSR-107 поможет в этом. Есть и другие небольшие исправления, которые не были освещены в этой статье, такие как улучшение обработки исключений и удобный метод putIfAbsent интерфейса Cache.

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

comments powered by Disqus