Caching is essential for improving application performance and reducing load on external resources. Spring Boot provides several annotations to manage caching in a flexible manner.
1. Understanding the Core Annotations
1.1 @Cacheable
- Purpose: Avoids method execution if a cached result is available.
- How it works:
- Checks if the key exists in cache.
- If present, returns cached value.
- If absent, executes the method and caches the result.
- Use case: Expensive calculations, external API calls, repeated GET requests.
@Cacheable(value = "weather", key = "#zip")
public int getWeather(String zip) {
// Method execution occurs only if cache doesn't exist
return fetchWeatherFromExternalService(zip);
}
Key points:
- Skips execution whenever possible.
- Caches results for future requests.
- Ideal for GET operations where the data is mostly read-only.
1.2 @CacheEvict
- Purpose: Removes cache entries.
- When to use: During updates, deletes, or when you want to refresh cached data.
- Important property:
beforeInvocation- If
true, cache is cleared before method execution. - Default: false (clears cache after successful method execution).
- If
@CacheEvict(value = "weather", key = "#zip", beforeInvocation = true)
public void clearWeatherCache(String zip) {
// Cache will be evicted before executing this method
}
Notes:
- Ensures stale data is removed.
- Critical for POST, PUT, DELETE operations where data changes.
1.3 @CachePut
- Purpose: Updates cache every time method executes.
- Difference from
@Cacheable:- Always executes the method.
- Stores the result in cache, overwriting existing entry.
@CachePut(value = "weather", key = "#zip")
public int updateWeather(String zip) {
return fetchWeatherFromExternalService(zip);
}
Use case:
- Hybrid approach where you want both execution and cache update.
- Useful for pre-fetching data periodically.
2. Practical Example: Weather Service with Scheduled Cache Updates
2.1 Use Case
- Application provides weather info to users.
- External API calls are slow or costly.
- Goal: Provide fast, reliable responses while keeping data reasonably fresh.
2.2 Service Layer
@Service
public class WeatherService {
private final ExternalWeatherService externalService;
public WeatherService(ExternalWeatherService externalService) {
this.externalService = externalService;
}
@Cacheable(value = "weather", key = "#zip")
public int getWeather(String zip) {
// Will be skipped if cached
return 0; // Placeholder
}
@Scheduled(fixedRate = 10000) // Every 10 seconds
@CachePut(value = "weather", key = "#zip")
public int updateWeather(String zip) {
// Periodically refreshes cache
return externalService.fetchWeather(zip);
}
}
2.3 External Service Simulation
@Service
public class ExternalWeatherService {
public int fetchWeather(String zip) {
// Simulate external API call
return new Random().nextInt(100); // Random temperature
}
}
2.4 Controller Layer
@RestController
@RequestMapping("/weather")
public class WeatherController {
private final WeatherService weatherService;
public WeatherController(WeatherService weatherService) {
this.weatherService = weatherService;
}
@GetMapping("/{zip}")
public int getWeather(@PathVariable String zip) {
return weatherService.getWeather(zip);
}
}
Behavior:
- First request for a ZIP code executes
getWeather()(returns cached value after first call). - Subsequent requests return cached results immediately.
- Scheduled method
updateWeather()updates the cache every 10 seconds, ensuring fresh data without impacting users.
3. Advantages
- Performance improvement: Users always get fast responses from cache.
- Reduced API costs: Fewer calls to external services.
- Controlled freshness: Scheduled updates ensure data is reasonably current.
- Flexible eviction:
@CacheEvictensures stale data is removed when necessary.
4. Limitations
- By default,
@Cacheabledoesn’t support automatic expiry. Redis TTL can be configured for this. - Limited flexibility for reactive streams and publisher types.
- Full support for reactive programming may require additional utilities or custom implementations.
5. Real-World Analogy
- Twitter feed, Netflix recommendations, or weather apps:
- Cached results provide instant response.
- Background services periodically update the cache.
- Users experience consistent, fast performance without waiting for expensive computations.
This approach demonstrates a robust caching strategy combining @Cacheable, @CachePut, @CacheEvict, and scheduled updates for efficient, high-performance applications.
