Implementing Redis Cache Preheating in Spring Boot with AbstractCache Pattern

This tutorial demonstrates how to implement Redis cache preheating in Spring Boot using an abstract cache class, ApplicationContextAware utility, and CommandLineRunner to automatically load hot data on startup, with a complete NewsCache example using RedisTemplate.

Architect's Guide
Architect's Guide
Architect's Guide
Implementing Redis Cache Preheating in Spring Boot with AbstractCache Pattern

What Is Cache Preheating?

Cache preheating is a strategy that proactively loads hotspot data into the cache after program startup or cache invalidation. When actual requests arrive, the hotspot data already exists in the cache, reducing cache penetration and cache breakdown while alleviating pressure on the SQL server.

Implementation

Abstract Cache Class

First, define an abstract base class that encapsulates the cache lifecycle. Subclasses implement the specific loading logic.

public abstract class AbstractCache {
    protected abstract void init();
    public abstract <T> T get();
    public abstract void clear();
    public void reload() {
        clear();
        init();
    }
}

Spring ApplicationContext Utility

A utility class implementing ApplicationContextAware to hold a static reference to the Spring ApplicationContext, enabling bean lookup from static contexts.

@Component
public class ApplicationContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextUtil.applicationContext = applicationContext;
    }
    public static ApplicationContext getContext() {
        return applicationContext;
    }
}

Cache Preheat Handler

A CommandLineRunner implementation that runs after Spring Boot startup. It retrieves all beans of type AbstractCache and invokes their init() method. The @ConditionalOnProperty annotation makes the preheating optional, controlled by cache.init.enable=true in configuration.

@Component
@ConditionalOnProperty(name = {"cache.init.enable"}, havingValue = "true", matchIfMissing = false)
public class CachePreheatHandler implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        ApplicationContext context = ApplicationContextUtil.getContext();
        Map<String, AbstractCache> beansOfType = context.getBeansOfType(AbstractCache.class);
        for (Map.Entry<String, AbstractCache> cacheEntry : beansOfType.entrySet()) {
            AbstractCache cache = context.getBean(cacheEntry.getValue().getClass());
            cache.init();
        }
    }
}

Configuration property:

cache.init.enable=true

Usage Example: News Hotspot Caching

The example uses a tb_news table containing Weibo hot-search sports entries.

Database table tb_news with news data
Database table tb_news with news data

Create a concrete implementation NewsCache extending AbstractCache. It uses RedisTemplate and a NewsService to load data. The init() method checks if the key exists; if not, it fetches the list from the service and stores it in Redis with a 30-minute TTL. The get() method reloads if the key is missing, ensuring data availability. The clear() method deletes the key.

@Component
@RequiredArgsConstructor
public class NewsCache extends AbstractCache {
    private static final String NEWS_KEY = "news";
    private final RedisTemplate<String, Object> redisTemplate;
    private final NewsService newsService;
    @Override
    protected void init() {
        if (Boolean.FALSE.equals(redisTemplate.hasKey(NEWS_KEY))) {
            redisTemplate.opsForValue().set(NEWS_KEY, newsService.list(), 30, TimeUnit.MINUTES);
        }
    }
    @Override
    public <T> T get() {
        if (Boolean.FALSE.equals(redisTemplate.hasKey(NEWS_KEY))) {
            reload();
        }
        return (T) redisTemplate.opsForValue().get(NEWS_KEY);
    }
    @Override
    public void clear() {
        redisTemplate.delete(NEWS_KEY);
    }
}

After starting the application, the hotspot data appears in Redis.

Redis keys showing cached news data
Redis keys showing cached news data

Controller Access

A REST controller exposes the cached data via GET /news/cache, delegating to NewsCache.get().

@RestController
@RequestMapping("/news")
@RequiredArgsConstructor
public class NewsController {
    private final NewsCache newsCache;
    @GetMapping("/cache")
    public List<News> list() {
        return newsCache.get();
    }
}
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.

RedisCachingSpring BootCommandLineRunnerAbstractCacheCache PreheatingRedisTemplateApplicationContextAware
Architect's Guide
Written by

Architect's Guide

Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.

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.