Refactoring Cache Logic with Spring Cache Annotations

The article explains how moving cache operations out of business code and into Spring Cache annotations—@Cacheable, @CachePut, and @CacheEvict—creates a clean, loosely‑coupled design, simplifies maintenance, and enables custom extensions such as breakdown protection and multi‑level caching for high‑concurrency applications.

DaTaobao Tech
DaTaobao Tech
DaTaobao Tech
Refactoring Cache Logic with Spring Cache Annotations

In daily coding practice, caches are widely used to handle high concurrency, but embedding cache APIs directly in business code leads to several issues:

Cache logic is scattered, violating high cohesion and low coupling.

Cache code is tightly coupled with business logic, reducing readability.

Switching cache implementations requires widespread code changes.

Common problems such as cache breakdown, penetration, and cascading need framework support.

This article focuses on how to extract cache code from business code to make it cleaner and more maintainable.

Traditional approach : Directly use cache APIs inside business methods, making the code hard to review.

Improved approach : Wrap cache operations in a simple API, but the calls are still embedded in business code.

Annotation‑based approach : Use Spring Cache annotations so that caching concerns are handled by a proxy, keeping business methods free of cache details.

Spring Cache leverages dynamic proxies (AOP) to intercept method calls and apply caching based on annotations such as @Cacheable, @CachePut, and @CacheEvict. Example:

@Cacheable(value = "user_cache", unless = "#result == null")
public User getUserById(Long id) {
    return userMapper.getUserById(id);
}

@CachePut(value = "user_cache", key = "#user.id", unless = "#result == null")
public User updateUser(User user) {
    userMapper.updateUser(user);
    return user;
}

@CacheEvict(value = "user_cache", key = "#id")
public void deleteUserById(Long id) {
    userMapper.deleteUserById(id);
}

Spring Cache is suitable for scenarios with moderate real‑time requirements (e.g., static pages, like counts). For high‑concurrency, large‑scale data, additional features such as multi‑level caching, periodic refresh, list caching, protection mechanisms, and counting are needed.

By building a custom cache framework on top of Spring Cache, one can retain its simplicity while adding missing capabilities like cache breakdown protection and distributed locks, further improving code readability and maintainability.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javaaopspring
DaTaobao Tech
Written by

DaTaobao Tech

Official account of DaTaobao Technology

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.