Using Caffeine Cache in Spring Boot: Features, Configuration, and Code Examples
This article introduces Caffeine Cache as a modern local caching solution, explains its W‑TinyLFU algorithm advantages over Guava, demonstrates various loading and eviction strategies, and provides detailed Spring Boot integration examples with Maven dependencies, configuration, annotations, and custom bean setups.
Guava Cache provides basic thread‑safe caching with simple LRU eviction, but Caffeine Cache builds on its ideas and adds a more advanced eviction algorithm called W‑TinyLFU, which combines LFU and LRU to achieve near‑optimal hit rates.
1. Algorithm Advantages – W‑TinyLFU
Caffeine improves on FIFO, LRU, and LFU by using a Count‑Min Sketch to record recent access frequencies and a sliding‑window reset to decay old data, allowing it to handle both steady‑state and bursty workloads efficiently.
2. Usage in Java
The library is available from Maven Central:
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.6.2</version>
</dependency>2.1 Manual Loading
public Object manualOperator(String key) {
Cache<String, Object> cache = Caffeine.newBuilder()
.expireAfterWrite(1, TimeUnit.SECONDS)
.expireAfterAccess(1, TimeUnit.SECONDS)
.maximumSize(10)
.build();
Object value = cache.get(key, t -> setValue(key).apply(key));
cache.put("hello", value);
Object ifPresent = cache.getIfPresent(key);
cache.invalidate(key);
return value;
}
public Function<String, Object> setValue(String key) {
return t -> key + "value";
}2.2 Synchronous Loading
public Object syncOperator(String key) {
LoadingCache<String, Object> cache = Caffeine.newBuilder()
.maximumSize(100)
.expireAfterWrite(1, TimeUnit.MINUTES)
.build(k -> setValue(key).apply(key));
return cache.get(key);
}2.3 Asynchronous Loading
public Object asyncOperator(String key) {
AsyncLoadingCache<String, Object> cache = Caffeine.newBuilder()
.maximumSize(100)
.expireAfterWrite(1, TimeUnit.MINUTES)
.buildAsync(k -> setAsyncValue(key).get());
return cache.get(key);
}
public CompletableFuture<Object> setAsyncValue(String key) {
return CompletableFuture.supplyAsync(() -> key + "value");
}3. Eviction Strategies
Caffeine supports three families of eviction policies:
Size‑based : .maximumSize() or .maximumWeight() with a custom .weigher().
Time‑based : .expireAfterAccess(), .expireAfterWrite(), or a custom .expireAfter(Expiry) implementation.
Reference‑based : .weakKeys(), .weakValues(), .softValues() (note that AsyncLoadingCache cannot use weak/soft references).
Examples:
// Size‑based eviction
LoadingCache<String, Object> cache = Caffeine.newBuilder()
.maximumSize(10000)
.build(key -> function(key));
// Time‑based eviction
LoadingCache<String, Object> cache = Caffeine.newBuilder()
.expireAfterAccess(5, TimeUnit.MINUTES)
.build(key -> function(key));3.1 Removal Listener
Cache<String, Object> cache = Caffeine.newBuilder()
.removalListener((String key, Object value, RemovalCause cause) ->
System.out.printf("Key %s was removed (%s)%n", key, cause))
.build();3.2 CacheWriter
LoadingCache<String, Object> cache = Caffeine.newBuilder()
.writer(new CacheWriter<String, Object>() {
@Override public void write(String key, Object value) { /* write to external store */ }
@Override public void delete(String key, Object value, RemovalCause cause) { /* delete from store */ }
})
.build(key -> function(key));4. Statistics
Cache<String, Object> cache = Caffeine.newBuilder()
.maximumSize(10_000)
.recordStats()
.build();
CacheStats stats = cache.stats(); // hitRate(), evictionCount(), averageLoadPenalty(), …5. Spring Boot Integration
Spring Boot 2.x replaces Guava with Caffeine as the default local cache. Add the following dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.6.2</version>
</dependency>Enable caching with @EnableCaching on the main application class.
5.1 Property‑Based Configuration
# application.properties
spring.cache.cache-names=cache1
spring.cache.caffeine.spec=initialCapacity=50,maximumSize=500,expireAfterWrite=10sOr YAML:
spring:
cache:
type: caffeine
cache-names:
- userCache
caffeine:
spec: maximumSize=1024,refreshAfterWrite=60sIf refreshAfterWrite is used, a CacheLoader<Object, Object> bean must be defined.
5.2 Bean‑Based Cache Manager
@Configuration
public class CacheConfig {
@Bean
public CacheLoader<String, Object> cacheLoader() {
return new CacheLoader<String, Object>() {
@Override public Object load(String key) { return null; }
@Override public Object reload(String key, Object oldValue) { return oldValue; }
};
}
@Bean @Primary
public CacheManager caffeineCacheManager() {
SimpleCacheManager manager = new SimpleCacheManager();
List<CaffeineCache> caches = new ArrayList<>();
caches.add(new CaffeineCache("userCache",
Caffeine.newBuilder()
.recordStats()
.expireAfterWrite(60, TimeUnit.SECONDS)
.maximumSize(10000)
.build()));
manager.setCaches(caches);
return manager;
}
}5.3 Cache Configuration Options
Common Caffeine spec keys include initialCapacity, maximumSize, maximumWeight, expireAfterAccess, expireAfterWrite, refreshAfterWrite, weakKeys, weakValues, softValues, and recordStats. Note that maximumSize and maximumWeight are mutually exclusive, as are weakValues and softValues.
6. Annotation‑Based Cache Operations
Spring Cache annotations simplify cache usage: @Cacheable – reads from cache or executes the method and stores the result. @CachePut – always executes the method and updates the cache. @CacheEvict – removes entries from the cache. @Caching – groups multiple cache annotations on a single method. @CacheConfig – defines common cache settings at the class level.
@Service
public class UserCacheService {
@Cacheable(value = "userCache", key = "#id", sync = true)
public void getUser(long id) { /* query DB */ }
@CachePut(value = "userCache", key = "#user.id")
public void saveUser(User user) { /* persist */ }
@CacheEvict(value = "userCache", key = "#user.id")
public void delUser(User user) { /* delete */ }
}SpEL can be used for keys (e.g., #id, #p0, or full expressions). The root object and method parameters are available for constructing cache keys.
7. Summary
Caffeine Cache offers a high‑performance, feature‑rich alternative to Guava Cache, with sophisticated eviction via W‑TinyLFU, flexible size‑, time‑, and reference‑based policies, statistics, removal listeners, and seamless Spring Boot integration through properties, YAML, or programmatic bean configuration. Using Spring’s caching annotations further simplifies cache management in Java backend applications.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
