Ashish Sarin is a Sun Certified Enterprise Architect with more than 13 years of experience in designing and developing Java EE applications. He is the author of Getting started with Spring Framework (self-published), Spring Roo 1.1 Cookbook (by Packt Publishing) and Portlets in Action (by Manning Publications). Ashish has posted 4 posts at DZone. You can read more from them at their website. View Full User Profile

Spring cache abstraction

02.07.2013
| 3550 views |
  • submit to reddit

This article is taken from the book  Getting started with Spring Framework 

If you want to use caching in your application, you can consider using Spring’s cache abstraction. Spring’s cache abstraction shields developers from directly dealing with the underlying caching implementation’s API. As of Spring 3.2, cache abstraction is available out-of-the-box for java.util.concurrent.ConcurrentMap, Ehcache and for caching solutions that implement JSR 107 – Java Temporary Caching API (referred to as JCACHE).

Spring provides a CacheManager interface that defines methods for managing a collection of Cache instances. A Cache instance is a wrapper around the underlying cache, and it provides methods for interacting with the underlying cache.

SimpleCacheManager (an implementation of CacheManager) is useful for simple caching scenarios and for testing purposes. For instance, if you want to use java.util.concurrent.ConcurrentMap as the underlying cache store, you can use SimpleCacheManager to manage the cache.

Let’s now look at how a CacheManager is configured in the application context XML file.

Configuring a CacheManager

If in an application a collection of java.util.concurrent.ConcurrentMap instances are used as the underlying cache store, then the SimpleCacheManager is used to manage the cache.

The following example listing shows how a SimpleCacheManager instance is configured:

<bean id="myCacheManager" class="org.springframework.cache.support.SimpleCacheManager">
    <property name="caches">
        <set>
            <bean
                class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean">
                <property name="name" value="fixedDepositList" />
            </bean>
            <bean
                class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean">
                <property name="name" value="fixedDeposit" />
            </bean>
        </set>
    </property>
</bean>


In the above example listing, the fixedDepositList and fixedDeposit caches are managed by the SimpleCacheManager instance.

Let's now look at different Spring annotations that are used for caching purposes.

 

Caching annotations - @Cacheable, @CacheEvict and @CachePut

To use caching annotations, you need to configure <annotation-driven> element of Spring’s cache schema, as shown here:

<beans . xmlns:cache="http://www.springframework.org/schema/cache"
    xsi:schemaLocation="..... http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
    <cache:annotation-driven cache-manager="myCacheManager" />
    .....
</beans>

In the above example listing, Spring’s cache schema is included so that its elements are accessible in the application context XML file. The <annotation-driven> element’s cache-manager attribute refers to the CacheManager bean that is used for managing the cache.

@Cacheable annotation on a method indicates that the value returned by the method is cached. The following example listing shows the usage of @Cacheable annotation to cache the value returned by FixedDepositService’s findFixedDepositsByBankAccount method:

package sample.spring.chapter07.springbankapp.service; 
import org.springframework.cache.annotation.Cacheable; 
..... 
@Service(value = "fixedDepositService") 
public class FixedDepositServiceImpl implements FixedDepositService { 
    ..... 
    @Cacheable(value = { "fixedDepositList" })
    public List<FixedDepositDetails> findFixedDepositsByBankAccount(int bankAccountId) { 
        logger.info("findFixedDepositsByBankAccount method invoked"); 
        return myFixedDepositDao.findFixedDepositsByBankAccount(bankAccountId); 
    } 
}

In the above example listing, the @Cacheable annotation specifies that the value returned by the findFixedDepositsByBankAccount method is stored in the fixedDepositList cache. It is important to note that @Cacheable annotated method is not invoked if the same set of argument values are passed to the method.

If you want to evict data from the cache when a method is called, annotate the method with the @CacheEvict annotation. The following example listing shows usage of @CacheEvict annotation:

package sample.spring.chapter07.springbankapp.service; 
import org.springframework.cache.annotation.CacheEvict; 
..... 
@Service(value = "fixedDepositService") 
public class FixedDepositServiceImpl implements FixedDepositService { 
    ..... 
    @CacheEvict(value = { "fixedDepositList" }, allEntries=true, beforeInvocation = true) 
    public void createFixedDeposit(final FixedDepositDetails fdd) throws Exception { 
        ..... 
    } 
    ..... 
}

The @CacheEvict annotation on the createFixedDeposit method instructs Spring to remove all the cached entries from the cache region named fixedDepositList. The value attribute specifies the cache region from which to evict the cached item, and allEntries attribute specifies whether or not all entries from the specified cache region are evicted.

Spring also provides a @CachePut annotation that indicates that a method is always invoked, and the value returned by the method is put into the cache.

Download samples.zip from here and refer to ch07-springbankapp project that shows the usage of Spring's cache abstraction.

Published at DZone with permission of its author, Ashish Sarin.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)