Как стать автором
Обновить

Кэширование данных в приложениях с Spring 3, размещенных в AppEngine

Время на прочтение7 мин
Количество просмотров6.5K
В этой статье я расскажу как можно кэшировать в memcache значения, возвращаемые методами bean'ов. Для этого не потребуется писать код, достаточно добавить конфигурации в xml файлы Spring'а и разметить код с помощью аннотаций.

Итак поредставим что у нас есть DAO с тремя методами — двумя для поиска сущностей и одним для сохранения сущностей. Для правильного функционирования нам нужен интерфейс и реализующий его класс (чтобы можно было добавить dynamic proxy на реализацию)


public interface SampleDAO {
    public Sample findById(int id);

    public Sample findByUrl(String url);

    public void save(Sample sample);
}

public class SampleDAOImpl  implements SampleDAO {
    public Sample findById(int id) { /* какой-то код */ }

    public Sample findByUrl(String url) { /* какой-то код */ }

    public void save(Sample sample) { /* какой-то код */ }
}


* This source code was highlighted with Source Code Highlighter.


И описание bean'а в конфигурации Spring'а

<bean id="sampleDAO" class="SampleDAOImpl">
    <property name="persistenceManagerFactory" ref="persistenceManagerFactory"/>
</bean>


* This source code was highlighted with Source Code Highlighter.


Теперь нам нужен какой-то компонент, который будет обрабатывать аннотации и сливать значения метода в кэш. Когда Spring был еще второй версии, то для него существовала библиотека spring-modules, которая позволяла это сделать. Проект был заброшен на какое-то время, но нашлись люди, которые стали развивать проект на github и их трудами мы воспользуемся.

Необходимо скачать последнюю версию исходников отсюда http://github.com/abashev/spring-modules и собрать их.

$ git clone git://github.com/abashev/spring-modules.git
$ cd spring-modules/projects
$ mvn install                        // Тут будет много ошибок, но нужный xml файл установится
$ cd spring-modules-cache
$ mvn install -DskipTests


* This source code was highlighted with Source Code Highlighter.


А теперь начинается уличная магия :) Добавляем аннотации в реализацию DAO

public class SampleDAOImpl {
    @Cacheable(modelId = "findByOldId")
    public Sample findById(int id) { /* какой-то код */ }

    @Cacheable(modelId = "findByUrl")
    public Sample findByUrl(String url) { /* какой-то код */ }

    @CacheFlush(modelId = "save")
    public void save(Sample sample) { /* какой-то код */ }
}


* This source code was highlighted with Source Code Highlighter.


Добавляем менеджер кэша в Spring context

<!-- Cache manager for Jsr107 cache -->
<bean id="cacheManager" class="org.springmodules.cache.provider.jsr107.Jsr107CacheManagerFactoryBean"/> 


* This source code was highlighted with Source Code Highlighter.


Объект cacheFacade используется для создания кэшей и настройки их параметров. Для того чтобы добавить специальные свойства для кэшей (для GAE это может быть настройка namespace и expire) необходимо переопределить свойство «cacheProperties».

<bean id="cacheProviderFacade" class="org.springmodules.cache.provider.jsr107.Jsr107CacheFacade">
    <property name="cacheManager" ref="cacheManager" />
    <property name="cacheProperties">
        <map>
            <entry key="findByOldId">
                <map>
                    <entry key="com.google.appengine.api.memcache.jsr107cache.NAMESPACE" value="findByOldId"/>
                </map>
            </entry>
            <entry key="findByUrl">
                <map>
                    <entry key="com.google.appengine.api.memcache.jsr107cache.NAMESPACE" value="findByUrl"/>
                </map>
            </entry>
        </map>
    </property>
</bean>


* This source code was highlighted with Source Code Highlighter.


Для того Spring корректно обработал аннотации необходимы три bean'а — один attribute collector, один caching interception и один caching advisor. Для обработки аннотации @Cachable

<bean id="cachingAttributeSource" class="org.springmodules.cache.annotations.AnnotationCachingAttributeSource"/>

<bean id="cachingInterceptor" class="org.springmodules.cache.interceptor.caching.MetadataCachingInterceptor">
    <property name="cacheProviderFacade" ref="cacheProviderFacade" />
    <property name="cachingAttributeSource" ref="cachingAttributeSource" />
    <property name="cachingModels">
        <map>
            <!-- Установка соответствия между значением modelId в аннотации и именем кэша -->
            <entry key="findByOldId">
                <bean class="org.springmodules.cache.provider.jsr107.Jsr107CacheCachingModel">
                    <constructor-arg value="findByOldId"/>
                </bean>
            </entry>
            <entry key="findByUrl">
                <bean class="org.springmodules.cache.provider.jsr107.Jsr107CacheCachingModel">
                    <constructor-arg value="findByUrl"/>
                </bean>
            </entry>
        </map>
    </property>
</bean>

<bean id="cachingAttributeSourceAdvisor" class="org.springmodules.cache.interceptor.caching.CachingAttributeSourceAdvisor">
    <constructor-arg ref="cachingInterceptor" />
</bean>


* This source code was highlighted with Source Code Highlighter.


Для обработки @CacheFlush

<bean id="flushingAttributeSource" class="org.springmodules.cache.annotations.AnnotationFlushingAttributeSource"/>

<bean id="flushingInterceptor" class="org.springmodules.cache.interceptor.flush.MetadataFlushingInterceptor">
    <property name="cacheProviderFacade" ref="cacheProviderFacade" />
    <property name="flushingAttributeSource" ref="flushingAttributeSource" />
    <property name="flushingModels">
        <map>
            <!-- Установка соответствия между значением modelId и именем кэша -->
            <entry key="save">
                <bean class="org.springmodules.cache.provider.jsr107.Jsr107CacheFlushingModel">
                    <constructor-arg value="findByOldId, findByUrl"/>
                </bean>
            </entry>
        </map>
    </property>
</bean>

<bean id="flushingAttributeSourceAdvisor" class="org.springmodules.cache.interceptor.flush.FlushingAttributeSourceAdvisor">
    <constructor-arg ref="flushingInterceptor" />
</bean>


* This source code was highlighted with Source Code Highlighter.


И последний штрих

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

* This source code was highlighted with Source Code Highlighter.
Теги:
Хабы:
Всего голосов 33: ↑28 и ↓5+23
Комментарии26

Публикации

Истории

Работа

Java разработчик
341 вакансия

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
11 сентября
Митап по BigData от Честного ЗНАКа
Санкт-ПетербургОнлайн
19 сентября
CDI Conf 2024
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
25 сентября
Конференция Yandex Scale 2024
МоскваОнлайн
28 – 29 сентября
Конференция E-CODE
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн