Spring Ehcache Configuration with @Cacheable Annotation
August 03, 2018
On this page, we will learn Spring 4 Ehcache configuration example with @Cacheable
annotation. Ehcache manages cache to boost performance our Spring application. Spring provides @Cacheable
annotation that uses cache name defined in Ehcache xml file. Spring provides EhCacheManagerFactoryBean
and EhCacheCacheManager
classes to configure and instantiate Ehcache. The JavaConfig must be annotated with @EnableCaching
annotation which enables annotation driven cache management. Here we will provide a complete example for Spring Ehcache Configuration.
build.gradle
Find the Gradle file to resolve JAR dependency for Spring and Ehcache.build.gradle
apply plugin: 'java' apply plugin: 'eclipse' archivesBaseName = 'concretepage' version = '1' repositories { mavenCentral() } dependencies { compile 'org.springframework.boot:spring-boot-starter:1.2.2.RELEASE' compile 'org.springframework:spring-context-support:4.1.5.RELEASE' compile 'net.sf.ehcache:ehcache-core:2.6.10' }
Project Structure in Eclipse
Find the project structure in eclipse.Configuration Class for EhCacheManagerFactoryBean and EhCacheCacheManager
The configuration class will be annotated with@EnableCaching
annotation and we need to create bean for EhCacheManagerFactoryBean
and EhCacheCacheManager
class.
@EnableCaching: It enables annotation driven cache management in Spring and is same as using
<cache:annotation-driven/>
in XML configuration.
EhCacheManagerFactoryBean: It assigns ehcache XML file by calling
EhCacheManagerFactoryBean.setConfigLocation()
. By passing true to setShared()
method, we enable our cache to be shared as singleton at the ClassLoader level. By default it is false
.
EhCacheCacheManager: This is a
CacheManager
backed by an EhCache. We can instantiate it by passing argument of EhCacheManagerFactoryBean.getObject()
.
Find the JavaConfig.
AppConfig.java
package com.concretepage; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.ehcache.EhCacheCacheManager; import org.springframework.cache.ehcache.EhCacheManagerFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.core.io.ClassPathResource; @Configurable @EnableCaching public class AppConfig { @Bean public Employee getEmployee(){ return new Employee(); } @Bean public CacheManager getEhCacheManager(){ return new EhCacheCacheManager(getEhCacheFactory().getObject()); } @Bean public EhCacheManagerFactoryBean getEhCacheFactory(){ EhCacheManagerFactoryBean factoryBean = new EhCacheManagerFactoryBean(); factoryBean.setConfigLocation(new ClassPathResource("ehcache.xml")); factoryBean.setShared(true); return factoryBean; } }
<cache:annotation-driven /> <bean id="employee" class="com.concretepage.Employee"/> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache"/> <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="classpath:ehcache.xml" p:shared="true"/>
ehcache.xml
Find the sampleehcache.xml
file. We have created a cache with the name empcache
that will be used by spring @Cacheable
annotation. Here maximum 5000 elements will be cached in memory and after that it will overflow to local disk. Any element will expire if it is idle for more than 200 seconds and alive for more than 500 seconds.
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect" dynamicConfig="true"> <cache name="empcache" maxEntriesLocalHeap="5000" maxEntriesLocalDisk="1000" eternal="false" diskSpoolBufferSizeMB="20" timeToIdleSeconds="200" timeToLiveSeconds="500" memoryStoreEvictionPolicy="LFU" transactionalMode="off"> <persistence strategy="localTempSwap"/> </cache> </ehcache>
Using @Cacheable
If we annotate our bean by Spring@Cacheable
annotation, it declares that it will be cached. We need to provide cache name defined in ehcache.xml
. In our example we have a cache named as empcache
in ehcache.xml
and we have provided this name in @Cacheable
. When Spring will hit the method for the first time, the result of that method will be cached and for same argument value, Spring will not hit the method next time. Once the cache is expired, then the Spring will hit the method again for the same argument value.
Employee.java
package com.concretepage; import org.springframework.cache.annotation.Cacheable; public class Employee { @Cacheable("empcache") public String getEmployee(int empId){ System.out.println("---Inside getEmployee() Method---"); if(empId==1){ return "Shankar"; }else{ return "Vishnu"; } } }
Test Spring Ehcache Application
Now we create a main method to test the application. Here if we call the method passing a value as an argument for the first time, Spring will hit the method. And for next time, if we pass the same argument value, we will get result from cache and not by running method.SpringDemo.java
package com.concretepage; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class SpringDemo { public static void main(String... args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppConfig.class); ctx.refresh(); Employee employee=(Employee) ctx.getBean(Employee.class); //calling getEmployee method first time. System.out.println("---Fetch Employee with id 1---"); System.out.println("Employee:"+ employee.getEmployee(1)); //calling getEmployee method second time. This time, method will not execute. System.out.println("---Again Fetch Employee with id 1, result will be fetched from cache---"); System.out.println("Employee:"+employee.getEmployee(1)); //calling getEmployee method third time with different value. System.out.println("---Fetch Employee with id 2---"); System.out.println("Employee:"+employee.getEmployee(2)); } }
Output
17:06:49.301 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'getEmployee' ---Fetch Employee with id 1--- ---Inside getEmployee() Method--- 17:06:49.323 [main] DEBUG net.sf.ehcache.store.disk.Segment - put added 0 on heap Employee:Shankar ---Again Fetch Employee with id 1, result will be fetched from cache--- Employee:Shankar ---Fetch Employee with id 2--- ---Inside getEmployee() Method--- 17:06:49.327 [main] DEBUG net.sf.ehcache.store.disk.Segment - put added 0 on heap Employee:Vishnu 17:06:49.332 [empcache.data] DEBUG net.sf.ehcache.store.disk.Segment - fault removed 0 from heap 17:06:49.332 [empcache.data] DEBUG net.sf.ehcache.store.disk.Segment - fault added 0 on disk