Core Cache Annotations
Spring Boot simplifies data caching through a declarative approach. To utilize the cache abstraction, ensure the @EnableCaching annotation is present on a configuration class. The framework manages storage based on method-level annotations.
Retrieving Cached Results
The @Cacheable annotation applies to read operations. When a method is called, the cache manager checks if an entry exists for the specified key. If found, the cached value is returned immediately; otherwise, the method executes, and its result is stored.
import org.springframework.cache.annotation.Cacheable;
public class ProductService {
@Cacheable(cacheNames = {"productStore"}, key = "#id")
public Product fetchProduct(Long id) {
return productRepo.findById(id);
}
}
If no default key generation strategy is defined, the first argument of the method often serves as the key.
Updating Cache Entries
Use @CachePut when you need to modify the underlying database but also want to ensure the cache reflects the new state. Unlike @Cacheable, this annotation forces method execution even if the cache already contains the target key.
import org.springframework.cache.annotation.CachePut;
public class ProductService {
@CachePut(cacheNames = {"productStore"}, key = "#result.productId")
public Product saveOrUpdate(Product entity) {
return productRepo.save(entity);
}
}
This pattern is essential for update methods to prevent stale data issues.
Evicting Cache Data
To maintain consistency during write operations that effect multiple records, use @CacheEvict. This removes specific entries or clears all entries associated with a named cache.
import org.springframework.cache.annotation.CacheEvict;
public class ProductService {
@CacheEvict(value = {"productStore", "categoryList"}, allEntries = true)
public void deleteCategory(Long categoryId) {
categoryRepo.deleteById(categoryId);
newsRepo.removeByCategoryId(categoryId);
}
}
Setting allEntries = true invalidates every item with in the specified namespace, ensuring no stale references remain.
Ehcache Integration Configuration
For persistent and distributed caching capabilities beyond the default simple provider, integrate Ehcache. First, declare the dependency in your build tool (e.g., Maven).
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.8.3</version>
</dependency>
Next, define a custom cache manager bean using Java configuration. This setup ensures Spring recognizes the external Ehcache instance.
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.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
@Configuration
@EnableCaching
public class CacheManagementConfig {
@Bean(name = "systemEhCacheManager")
public EhCacheCacheManager initializeCacheManager(EhCacheManagerFactoryBean factoryBean) {
return new EhCacheCacheManager(factoryBean.getObject());
}
@Bean
public EhCacheManagerFactoryBean configureFactory() {
EhCacheManagerFactoryBean factory = new EhCacheManagerFactoryBean();
factory.setConfigLocation(new ClassPathResource("/custom-ehcache-config.xml"));
factory.setShared(true);
return factory;
}
}
Finally, provide the XML schema definition located at src/main/resources/custom-ehcache-config.xml. Define regions for memory limits, time-to-live, and eviction policies.
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<diskStore path="java.io.tmpdir/Application_Cache_Data" />
<defaultCache eternal="false" maxElementsInMemory="10000"
overflowToDisk="true" diskPersistent="false"
timeToIdleSeconds="120" timeToLiveSeconds="300"
memoryStoreEvictionPolicy="LRU" />
<cache name="productStore" eternal="false" maxElementsInMemory="5000"
overflowToDisk="false" diskPersistent="false"
timeToIdleSeconds="60" timeToLiveSeconds="180"
memoryStoreEvictionPolicy="LRU" />
<cache name="categoryList" eternal="false" maxElementsInMemory="2000"
overflowToDisk="false" diskPersistent="false"
timeToIdleSeconds="0" timeToLiveSeconds="180"
memoryStoreEvictionPolicy="LRU" />
</ehcache>
These configurations allow fine-grained control over how long data persists and how it is evicted based on usage patterns.