Skip to content

Spring Boot 基于 CommandLineRunner 扩展点应用加载缓存信息的 starter

前言

CommandLineRunner 接口是一个函数式接口,包含一个 run() 方法,该方法在 Spring Boot 应用程序启动后被自动调用。通过实现 CommandLineRunner 接口,开发者可以定义一系列需要在应用程序启动后执行的初始化操作,如加载初始化数据、启动后打印应用信息、启动异步任务等。此前,我们已在一篇文章中详细介绍了如何利用 CommandLineRunner 获取 Web 项目的所有 URL(Spring Boot 基于 CommandLineRunner 扩展点获取 Web 项目所有 URL)。

需求背景

在实际应用中,为了提升应用的性能和响应速度,我们常常需要在 Spring Boot 应用启动完成后立即将一些相对固定的数据从数据库加载到缓存中。这些数据包括但不限于枚举值、前端所需的配置信息等。通过预先加载这些数据到缓存中,可以有效避免每次请求时都需要查询数据库,从而显著提高应用的性能和用户体验。 为了满足这一需求,并确保应用的通用性和代码的规范化,我们设计并开发了一个 Starter。该 Starter 允许应用系统通过继承我们定义的类并实现相关的方法,轻松实现启动时的数据加载和缓存初始化。这不仅简化了开发流程,还提高了代码的可维护性和复用性。

定义抽象类

我们首先定义一个抽象类 AbstractCache,用于封装缓存的基本操作,如加载、获取、清空和重新加载缓存。

java
/**
 * 抽象缓存预热组件
 */
public abstract class AbstractCache {

    /**
     * 加载缓存
     */
    public void load() {};

    /**
     * 获取缓存
     * @param key
     * @return
     * @param <T>
     */
    public <T> T get(String key) {
        return null;
    };


    /**
     * 清空缓存
     */
    public void clear() {}

    /**
     * 重加载缓存
     */
    public void reload() {
        clear();
        load();
    }
}

实现 CommandLineRunner 加载缓存

接下来,我们实现 CommandLineRunner 接口,定义一个 LoadRedisCacheCommandLinerRunner 类,用于在应用启动时加载缓存。

java
@Slf4j
public class LoadRedisCacheCommandLinerRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        log.info("executor load cache runner");
        ApplicationContext context = SpringContextUtils.getApplicationContext();
        Map<String, AbstractCache> beans = context.getBeansOfType(AbstractCache.class);
        if (beans.isEmpty()) {
            return;
        }
        for (Map.Entry<String, AbstractCache> entry : beans.entrySet()) {
            AbstractCache cache = (AbstractCache)SpringContextUtils.getBean(entry.getValue().getClass());
            cache.load();
        }
    }
}

配置 LoadRedisCacheCommandLinerRunner

我们需要在配置类中注册 LoadRedisCacheCommandLinerRunner,并确保 SpringContextUtils 被正确初始化

java
@Configuration
public class RedisCacheAutoConfig {

    @Bean
    public SpringContextUtils springContextUtils() {
        return new SpringContextUtils();
    }

    @Bean
    @ConditionalOnBean(SpringContextUtils.class)
    public LoadRedisCacheCommandLinerRunner loadRedisCacheCommandLinerRunner() {
        return new LoadRedisCacheCommandLinerRunner();
    }
}

自动配置

为了使我们的 Starter 能够自动配置,需要在 META-INF 目录下创建 spring.factories 文件,指定自动配置类。

text
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.ssn.kit.cache.config.RedisCacheAutoConfig

测试

引入依赖 在应用系统的 pom.xml 文件中引入我们开发的 Starter 依赖。

xml
<dependency>
    <groupId>com.ssn.kit</groupId>
    <artifactId>corp-kit-tiered-cache</artifactId>
    <version>1.0-SNAPSHOT</version>
    <scope>compile</scope>
</dependency>

编写具体需要加载到缓存的类

创建一个具体的缓存类 ConfigCache,继承 AbstractCache 并实现相关方法。

java
@Component
@Slf4j
public class ConfigCache extends AbstractCache {

    private Map<String,String> map = new HashMap<String,String>();

    /**
     * 加载缓存
     */
    @Override
    public void load() {
        log.info("load config cache");
        map.put("url","www.baidu.com");
        map.put("mode","dev");
    }


    @Override
    public String get(String key) {
        return map.get(key);
    }

}

启动程序

启动 Spring Boot 应用程序,可以看到相关的日志输出,确认缓存加载成功。

text
2024-11-21 15:11:39.985  INFO 1656 --- [           main] com.kit.demo.runner.ConfigCache          : Loading configuration cache

结论

通过上述实现,我们成功地在 Spring Boot 应用启动时使用 CommandLineRunner 加载缓存,从而显著提升了应用的性能和响应速度。CommandLineRunner 提供了一个简单而强大的方式来执行启动时的任务,非常适合用来初始化缓存、预热数据等操作.

Released under the MIT License.