0
0
Spring Bootframework~15 mins

@CachePut for updating cache in Spring Boot - Deep Dive

Choose your learning style9 modes available
Overview - @CachePut for updating cache
What is it?
@CachePut is an annotation in Spring Boot used to update the cache with the latest method result every time the method is called. Unlike @Cacheable, which skips method execution if the cache has data, @CachePut always runs the method and then refreshes the cache. This helps keep cached data fresh without skipping the actual method logic. It is mainly used when you want to update cache entries after modifying data.
Why it matters
Without @CachePut, caches can become stale because they only update when data is first requested or explicitly cleared. This can cause users to see outdated information, leading to confusion or errors. @CachePut solves this by ensuring the cache always reflects the latest data after updates, improving application performance and user experience by combining fresh data with fast access.
Where it fits
Before learning @CachePut, you should understand basic caching concepts and the @Cacheable annotation in Spring Boot. After mastering @CachePut, you can explore cache eviction with @CacheEvict and advanced cache configurations like custom key generators and cache managers.
Mental Model
Core Idea
@CachePut always runs the method and updates the cache with its result, ensuring the cache stays fresh after data changes.
Think of it like...
Imagine a bulletin board where you always post the latest news after checking the source, even if the board already has an old notice. You replace the old notice with the new one every time you get an update.
┌───────────────┐       ┌───────────────┐
│ Method Call   │──────▶│ Method Runs   │
└───────────────┘       └───────────────┘
                              │
                              ▼
                     ┌─────────────────┐
                     │ Cache Updated   │
                     │ with New Result │
                     └─────────────────┘
Build-Up - 7 Steps
1
FoundationBasic caching concept in Spring Boot
🤔
Concept: Caching stores method results to speed up repeated calls with the same inputs.
Spring Boot uses annotations like @Cacheable to save method results in a cache. When a method annotated with @Cacheable is called, Spring checks if the result is already cached. If yes, it returns the cached result without running the method again.
Result
Repeated calls with the same inputs return cached results instantly, improving performance.
Understanding caching basics is essential because @CachePut builds on this idea but changes when the cache updates.
2
FoundationDifference between @Cacheable and @CachePut
🤔
Concept: @Cacheable skips method execution if cached data exists; @CachePut always runs the method and updates the cache.
With @Cacheable, if the cache has data, the method is not executed again. With @CachePut, the method runs every time, and its result replaces the cache entry. This means @CachePut is used when you want to refresh the cache after data changes.
Result
You get fresh data in the cache every time the method runs with @CachePut, unlike @Cacheable which may return stale data.
Knowing this difference helps decide when to use @CachePut to keep cache data fresh after updates.
3
IntermediateUsing @CachePut to update cache after data change
🤔Before reading on: Do you think @CachePut prevents method execution if cache exists, or always runs the method? Commit to your answer.
Concept: @CachePut runs the method every time and updates the cache with the new result.
Annotate a method that modifies data with @CachePut and specify the cache name and key. When this method runs, it updates the cache entry with the latest data. For example: @CachePut(value = "users", key = "#user.id") public User updateUser(User user) { // update user in database return user; } This ensures the cache 'users' always has the updated user info.
Result
Cache entries reflect the latest data immediately after updates, avoiding stale cache problems.
Understanding that @CachePut forces method execution and cache update prevents common bugs where cache is not refreshed after data changes.
4
IntermediateCombining @CachePut with @Cacheable for read-write caching
🤔Before reading on: Can you use @CachePut and @Cacheable on the same method? Why or why not? Commit to your answer.
Concept: Use @Cacheable for read methods to cache results and @CachePut for write methods to update cache after changes.
Typically, you use @Cacheable on methods that read data to avoid repeated database calls. Use @CachePut on methods that modify data to update the cache. For example: @Cacheable(value = "users", key = "#id") public User getUser(Long id) { ... } @CachePut(value = "users", key = "#user.id") public User updateUser(User user) { ... } This pattern keeps cache consistent and efficient.
Result
Reads are fast from cache, and writes keep cache fresh without manual cache clearing.
Knowing how to separate read and write caching responsibilities avoids cache inconsistencies and improves app performance.
5
AdvancedCustomizing cache keys with @CachePut
🤔Before reading on: Do you think @CachePut uses method parameters or return values to generate cache keys by default? Commit to your answer.
Concept: @CachePut allows custom cache key expressions using SpEL (Spring Expression Language) for precise cache control.
By default, @CachePut uses method parameters to generate cache keys. You can customize keys using the 'key' attribute with SpEL. For example: @CachePut(value = "users", key = "#user.email") public User updateUser(User user) { ... } This caches the user by email instead of ID. You can also combine parameters or use complex expressions.
Result
Cache keys match your application's logic, preventing collisions and improving cache hit rates.
Understanding key customization prevents subtle bugs where cache entries overwrite each other or are missed.
6
AdvancedHandling cache update failures gracefully
🤔Before reading on: If cache update fails in @CachePut, does the method execution fail or succeed? Commit to your answer.
Concept: By default, cache update failures do not stop method execution, but you can customize error handling.
Spring's cache abstraction catches cache exceptions so the method still returns normally even if cache update fails. You can configure cache error handlers to log or handle failures differently. This prevents cache issues from breaking your business logic.
Result
Your application remains stable even if the cache system has problems.
Knowing this behavior helps design resilient systems that separate cache reliability from core logic.
7
ExpertInternal proxy mechanism of @CachePut in Spring AOP
🤔Before reading on: Does @CachePut modify the original method code or use proxies to add caching behavior? Commit to your answer.
Concept: @CachePut works by Spring creating a proxy around the method that intercepts calls to update the cache after method execution.
Spring uses Aspect-Oriented Programming (AOP) proxies to add caching behavior. When a method annotated with @CachePut is called, the proxy runs the method, captures the result, and then updates the cache. The original method code remains unchanged. This proxy mechanism allows caching to be added declaratively without modifying business logic.
Result
Caching is transparent to your code but powerful and flexible under the hood.
Understanding the proxy-based implementation explains why self-invocation inside the same class bypasses caching and how to avoid this common pitfall.
Under the Hood
@CachePut uses Spring's AOP proxies to intercept method calls. When the method runs, the proxy captures the return value and updates the cache with the specified key and cache name. The cache update happens after the method completes successfully. This mechanism separates caching logic from business code, making caching declarative and reusable.
Why designed this way?
Spring chose proxy-based AOP to add cross-cutting concerns like caching without changing existing code. This design allows developers to add caching declaratively via annotations, keeping business logic clean. Alternatives like bytecode manipulation were more complex and less transparent. The proxy approach balances flexibility, simplicity, and maintainability.
┌───────────────┐
│ Client Calls  │
└──────┬────────┘
       │
┌──────▼───────┐
│ Spring Proxy │
│ (@CachePut)  │
└──────┬───────┘
       │
┌──────▼───────┐
│ Original     │
│ Method Runs  │
└──────┬───────┘
       │
┌──────▼───────┐
│ Cache Updated│
│ with Result  │
└──────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does @CachePut skip method execution if cache has data? Commit yes or no.
Common Belief:@CachePut behaves like @Cacheable and skips method execution if cache entry exists.
Tap to reveal reality
Reality:@CachePut always executes the method and updates the cache regardless of existing cache entries.
Why it matters:Believing this causes bugs where updates are not applied because the method never runs, leading to stale cache and data inconsistency.
Quick: Can @CachePut be used on methods that only read data? Commit yes or no.
Common Belief:@CachePut is suitable for any method, including read-only methods.
Tap to reveal reality
Reality:@CachePut is intended for methods that modify data and need to update the cache; using it on read-only methods causes unnecessary cache updates and performance loss.
Why it matters:Misusing @CachePut on read methods wastes resources and can degrade application performance.
Quick: Does @CachePut update the cache before or after method execution? Commit your answer.
Common Belief:@CachePut updates the cache before the method runs to prepare for the result.
Tap to reveal reality
Reality:@CachePut updates the cache only after the method successfully returns its result.
Why it matters:Assuming cache updates happen before method execution can lead to incorrect assumptions about cache state during method logic.
Quick: If a method annotated with @CachePut calls another method with @CachePut in the same class, will caching happen? Commit yes or no.
Common Belief:Self-invocation triggers caching annotations as usual.
Tap to reveal reality
Reality:Self-invocation bypasses Spring proxies, so caching annotations like @CachePut are ignored in internal calls.
Why it matters:This causes unexpected cache misses or stale data when methods call each other internally, confusing developers.
Expert Zone
1
The order of multiple caching annotations (@CachePut, @CacheEvict) on the same method affects cache state and must be carefully managed.
2
Using @CachePut with asynchronous methods requires attention because cache updates happen after method completion, which may be delayed.
3
Cache key generation can be customized with SpEL to handle complex scenarios like composite keys or conditional caching.
When NOT to use
@CachePut is not suitable when you want to skip method execution if cached data exists; use @Cacheable instead. Also avoid @CachePut on read-only methods to prevent unnecessary cache updates. For cache eviction scenarios, use @CacheEvict. For complex cache refresh strategies, consider manual cache management or external cache tools.
Production Patterns
In production, @CachePut is commonly used in service methods that update database records to keep caches synchronized. It is combined with @Cacheable on read methods for efficient caching. Developers often customize cache keys for multi-tenant or user-specific data. Error handling strategies ensure cache failures do not impact business logic. Monitoring cache hit rates and eviction policies helps maintain performance.
Connections
Aspect-Oriented Programming (AOP)
Builds-on
Understanding AOP explains how @CachePut adds caching behavior transparently without changing business code.
Database Transaction Management
Complementary
Knowing transaction boundaries helps ensure cache updates with @CachePut happen only after successful data commits, preventing cache inconsistency.
Memory Management in Operating Systems
Analogous
Just like OS manages memory cache to speed up access while keeping data fresh, @CachePut manages application cache to balance speed and data accuracy.
Common Pitfalls
#1Cache not updating after data changes
Wrong approach:@Cacheable(value = "users", key = "#user.id") public User updateUser(User user) { // update logic return user; }
Correct approach:@CachePut(value = "users", key = "#user.id") public User updateUser(User user) { // update logic return user; }
Root cause:Using @Cacheable on update methods causes cache to return stale data without running the update logic.
#2Cache update ignored on internal method calls
Wrong approach:public void updateAllUsers(List users) { for (User u : users) { updateUser(u); // updateUser has @CachePut } }
Correct approach:Use self-injection or call updateUser via Spring proxy: @Autowired private UserService self; public void updateAllUsers(List users) { for (User u : users) { self.updateUser(u); } }
Root cause:Self-invocation bypasses Spring proxies, so caching annotations are not applied.
#3Incorrect cache key causing collisions
Wrong approach:@CachePut(value = "users", key = "#user") public User updateUser(User user) { ... }
Correct approach:@CachePut(value = "users", key = "#user.id") public User updateUser(User user) { ... }
Root cause:Using the whole object as key can cause cache misses or collisions if equals/hashCode are not properly defined.
Key Takeaways
@CachePut always runs the method and updates the cache with its result, ensuring fresh data after updates.
It differs from @Cacheable, which may skip method execution if cached data exists.
Use @CachePut on methods that modify data and want to refresh cache entries immediately.
Spring uses proxies to implement @CachePut, so internal method calls bypass caching unless proxied.
Custom cache keys and error handling improve cache accuracy and application resilience.