How does Spring Boot caching work using @Cacheable?
Spring Boot simplifies caching integration by providing annotations like `@Cacheable` to declaratively add caching capabilities to applications. This mechanism helps improve application performance by storing the results of expensive method calls and returning the cached result when the same input occurs again, avoiding redundant computations.
Overview of Spring Boot Caching
Spring Boot's caching abstraction allows developers to apply caching to methods without having to deal with the underlying caching infrastructure directly. It provides a consistent set of annotations to trigger caching operations, delegating the actual storage and retrieval to a configured cache provider.
Enabling Caching
To enable caching in a Spring Boot application, you need to add the @EnableCaching annotation to one of your configuration classes (often your main application class). This annotation activates Spring's caching features.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching // Enable caching
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Using @Cacheable
The @Cacheable annotation is applied to a method to indicate that its result can be cached. When an @Cacheable method is called, Spring checks if the method has already been executed with the same arguments. If a cached value is found, it's returned immediately, bypassing the method execution. If not, the method is executed, its result is stored in the cache, and then returned.
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class ProductService {
// The 'products' cache will store results. The 'id' parameter is used as default key.
@Cacheable("products")
public Product getProductById(Long id) {
// Simulate an expensive operation (e.g., database call)
System.out.println("Fetching product with ID: " + id + " from database...");
try {
Thread.sleep(1000); // Simulate delay
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return new Product(id, "Product " + id, 99.99);
}
// Example Product class (for context)
private static class Product {
Long id;
String name;
double price;
public Product(Long id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
}
}
Key Parameters of @Cacheable
valueorcacheNames: (required) Specifies the name(s) of the cache(s) to use. If multiple caches are specified, the method will be cached in all of them.key: (optional) Defines the key for the cache entry. By default, Spring uses aSimpleKeyGeneratorthat generates a key from all method parameters. You can provide SpEL (Spring Expression Language) to create a custom key (e.g.,key = "#id"for a method parameterid).condition: (optional) A SpEL expression evaluated before the method invocation. The method will be cached only if the expression evaluates totrue(e.g.,condition = "#id > 0").unless: (optional) A SpEL expression evaluated after the method invocation. The method's result will *not* be cached if this expression evaluates totrue(e.g.,unless = "#result == null"to avoid caching null results).
Cache Providers
Spring's caching abstraction is provider-agnostic. Spring Boot auto-configures a suitable CacheManager based on the dependencies present in your classpath. Common cache providers include:
- ConcurrentMapCacheManager (default, in-memory, for development/testing)
- EhCache
- Caffeine
- Redis
- JCache (JSR-107 compliant providers like Hazelcast)
You typically add the starter dependency for your chosen provider (e.g., spring-boot-starter-cache along with caffeine or spring-data-redis) and Spring Boot handles the basic configuration.
Cache Management
Behind the scenes, Spring uses a CacheManager interface to manage caches. This CacheManager is responsible for creating, configuring, and retrieving Cache instances. While Spring Boot auto-configures a default, you can also define your own CacheManager bean for more fine-grained control over cache settings.