Кеширование в Spring Framework 3.1

    Я могу ошибаться, но мне кажется что всем хорошо известный Spring Framework достиг своей вершины к версии 2.5 (когда внедрили активное использование аннотаций) и дальше идет по сути дела «полировка» — даже major-релиз 3.0 не сильно отличается от 2.5. Тоже самое можно сказать и про грядущий 3.1 — небольшие улучшения, фишечки — но не более того. Однако одна «фишечка» в 3.1 показалась мне особенно интересной — это кеширование.
    image

    В любом разрабатываемом приложении мы можем в какой-то момент столкнутся с проблемой производительности. Один из способов решения проблем — это кеширование. Естественно можно кешировать данные возвращаемые из базы данных (Hibernate — наиболее используемый в java делает это и так) — но намного интересней — это кеширование значений возвращаемых с уровня «сервисов». Вычисление таких значений может быть достаточно трудоемким, включать множество вызовов к базе данных, другим сервисам, вычислений — и соответсвенно кеширование на этом уровне может привести к более весомым результатам.
    В Spring Framework 3.1 это можно будет сделать с помощью аннотации @Cacheable
    На самом деле — кеширование на уровне сервисов можно было сделать в Spring Framework и раньше, просто теперь это станет намного проще.
    Кеширование значений

    Например, если в ходе профилирования вы выяснили, что «тупит» какой-то определенный метод, например (как в документации) метод возвращения книги по ISBN:

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

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

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

    Данная аннотация сама повесит interceptor, создаст ключ по параметрам, проверит есть ли значение в кеше, если нет — вызовет метод и закеширует результат.

    И это все? Почти, для полноты надо:
    Настроить кеширование в приложении

    Это делается в xml-файле конфигурации application context-а:

    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xsi:schemaLocation="http://www.springframework.org/schema/beans www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/cache www.springframework.org/schema/cache/spring-cache.xsd">
    <cache:annotation-driven />

    и настроить cache-manager — например простейший (использующий ConcurrentMap)

    <bean class="org.springframework.cache.concurrent.ConcurrentCacheFactoryBean" p:name="default"/>
    <bean class="org.springframework.cache.concurrent.ConcurrentCacheFactoryBean" p:name="books"/>




    либо ehcache (можно использовать и другие реализации):

    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhcacheCacheManager" p:cache-manager="ehcache"/>
    <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="ehcache.xml"/>

    Очистка кеша

    Кешировать данные надо аккуратно — это всегда потенциальный источник ошибок, когда данные обновились, а кеш нет и приложение использует устаревшие данные. Очистка кеша тоже может быть выполнена при помощи аннотации — @CacheEvict:

    @CacheEvict(value = "books", allEntries=true)
    public void loadBooks(InputStream batch)


    Вот и все. Просто? Вроде да. На самом деле механизм кеширования достаточно гибкий, там есть ряд дополнительных возможностей (как например написание собственных аннотаций, генерация ключей и много другое. Но основная функциональность выглядит вот так вот просто.
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 12

      +2
      и правда просто
        0
        Не так давно видел статью про мемоизацию возвращаемых значений, как я понимаю, именно этот подход здесь и используется?
          0
          Не очень в курсе что такое «мемоизация» — но в прицнипе возможность кеширования (меморизация?) возвращаемых значений была и раньше — как минимум в Spring Framework 2.5 я это уже использовал — просто делалось это сложней (навешиванием интерсепторов которые и выполняли кеширование). Фишка 3.1 именно в упрощении данного процесса
            0
            Ага, с аннотациями всё выглядит очень лаконично.
          +1
          Вот так оно бывает — habrahabr.ru/blogs/java/98972/
            0
            Во кстати! Спасибо! Хороший пример того как можно использовать memcache GAE, только в Spring 3.1 теперь это получается проще, потому как @Cacheable есть по умолчанию — не надо плясать с бубном вокруг spring-modules
              0
              Ну там плясать не надо — подключить и пользовать, вроде все расписал подробно. Если есть вопросы то обращайтесь :))
            0
            Где-то я это уже видел :) Но в целом — молодцы, радует, что этот кеширование на основе аннотаций официально становиться частью Spring'a.
              0
              Правильно я понимаю, что KeyGenerator учитывает только входные параметры и не учитывает состояние объекта?
                0
                Ну данный метод предполагается к использованию сервисов — которые рекомендуется делать stateless
                0
                Все хорошо и красиво. Но стремление все сделать Generic иногда выходит боком. Явное — лучше не явного. Сложно сказать что-то о пермпективе такой технологии кеширования для каких-то сложных случаев.
                  0
                  Здравствуйте, мне нужно удалить весь кеш. ТОисть все задекларированные «кешы» в «ehcache.xml». Не подскажете, может есть какая команда, аннотация?? Смотрел на офф сайте, не нашел.
                  Есть только как вы и написали, — удалить одиночный кеш.
                  @CacheEvict(value = «books», allEntries=true)
                  public void loadBooks(InputStream batch)

                  а по большому счету, я же не должен параметры передавать если они мне не нужны… Здесь InputStream просто как пример?
                  Спасибо!

                  Only users with full accounts can post comments. Log in, please.