📜 ⬆️ ⬇️

Data caching in Spring 3 applications hosted on AppEngine

In this article, I’ll tell you how to cache the values ​​returned by the bean methods in memcache. You do not need to write code, it is enough to add configurations to Spring's xml files and mark up the code using annotations.

So, we assume that we have a DAO with three methods — two for searching entities and one for saving entities. For proper functioning, we need an interface and a class that implements it (so that we can add a dynamic proxy to the implementation)


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 .

')
And the description of the bean in the Spring configuration

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


* This source code was highlighted with Source Code Highlighter .


Now we need some component that will handle the annotations and merge the method values ​​into the cache. When Spring was still the second version, there was a spring-modules library for it, which allowed it to be done. The project was abandoned for a while, but there were people who began to develop the project on github and we will use their work.

You need to download the latest version of the source code from here http://github.com/abashev/spring-modules and compile them.

$ 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 .


And now street magic begins :) Add annotations to the DAO implementation

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 .


Add cache manager in 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 .


The cacheFacade object is used to create caches and set their parameters. In order to add special properties for caches (for GAE this may be the namespace and expire setting), you must override the “cacheProperties” property.

< 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 .


In order for Spring to correctly process the annotations, three beans are needed — one attribute collector, one caching interception, and one caching advisor. To process the @Cachable annotation

< 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 .


To handle @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 .


And the final touch

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

* This source code was highlighted with Source Code Highlighter .

Source: https://habr.com/ru/post/98972/


All Articles