You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中如何在启动时用Caffeine Cache调用@Cacheable预加载数据库数据?

嘿,作为缓存新手,咱们一步步来搞定这个需求——Spring Boot启动时把数据库数据塞进Caffeine缓存,之后直接读缓存不用碰DAO。别担心,每一步都很接地气,跟着做就行!

1. 先加依赖,把Caffeine和Spring Cache拉进来

首先得让项目支持Spring Cache和Caffeine,咱们用Maven或者Gradle都可以:

Maven(pom.xml)

<dependencies>
    <!-- Spring Boot Cache 起步依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    <!-- Caffeine 缓存实现 -->
    <dependency>
        <groupId>com.github.ben-manes.caffeine</groupId>
        <artifactId>caffeine</artifactId>
    </dependency>
    <!-- 数据库相关依赖(比如Spring Data JPA,根据你的实际情况调整) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

Gradle(build.gradle)

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-cache'
    implementation 'com.github.ben-manes.caffeine:caffeine'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'com.h2database:h2'
}
2. 配置Caffeine缓存规则

在application.yml里配置缓存的基础参数,新手不用搞太复杂,先配实用的:

spring:
  cache:
    type: caffeine
    caffeine:
      spec: initialCapacity=50,expireAfterAccess=3600s # 初始容量50,访问后1小时过期
    cache-names: usersCache # 提前定义缓存名称,后面和@Cacheable对应

简单解释下:

  • initialCapacity:缓存初始能存多少条数据,避免频繁扩容
  • expireAfterAccess:数据多久没人访问就自动过期,这里设的1小时
  • cache-names:给咱们的缓存起个专属名字,后面要用它定位缓存
3. 开启Spring缓存支持

在你的Spring Boot启动类上加@EnableCaching注解,告诉Spring:“嘿,我要启用缓存功能啦!”

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching // 关键注解,必须加!
public class CacheDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(CacheDemoApplication.class, args);
    }
}
4. 写业务代码,实现启动加载+缓存逻辑

咱们分三层来写:DAO(负责查数据库)、Service(加缓存注解)、启动触发逻辑(提前加载缓存)。

第一步:DAO层(从数据库拿数据)

假设咱们要缓存用户数据,写个简单的DAO接口:

import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.entity.User;

public interface UserDao extends JpaRepository<User, Long> {
    // 用JPA自带的findAll,自动实现从数据库查询所有用户
}

对应的User实体类(简单示例):

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    // 记得补全构造方法、getter、setter哦
}

第二步:Service层(加@Cacheable核心注解)

这里是实现缓存的关键!在Service的方法上加上@Cacheable,指定咱们之前配置的缓存名usersCache。这样第一次调用这个方法时,会执行方法体(查数据库),然后把结果存进缓存;之后再调用,直接从缓存拿数据,完全不会碰数据库。

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class UserService {
    private final UserDao userDao;

    // 构造注入DAO
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    // @Cacheable:第一次调用查数据库,之后直接读缓存
    // value指定缓存名称,和配置文件里的cache-names对应
    @Cacheable(value = "usersCache")
    public List<User> getAllUsers() {
        System.out.println("正在从数据库查询用户数据..."); // 加个日志,方便验证缓存是否生效
        return userDao.findAll();
    }
}

第三步:启动时主动触发缓存加载

现在要让Spring Boot启动时就调用getAllUsers(),把数据提前塞进缓存。咱们用ApplicationRunner来实现——这是Spring提供的、启动完成后自动执行代码的接口。

可以直接在启动类里加个Bean:

import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableCaching
public class CacheDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(CacheDemoApplication.class, args);
    }

    // 启动时执行这个方法,触发缓存加载
    @Bean
    public ApplicationRunner cacheLoader(UserService userService) {
        return args -> {
            System.out.println("启动时加载用户数据到缓存...");
            userService.getAllUsers(); // 调用带@Cacheable的方法,触发缓存写入
        };
    }
}
5. 验证效果,看看缓存是不是真的生效了

写个简单的Controller来测试:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

@RestController
public class UserController {
    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/users")
    public List<User> getUsers() {
        return userService.getAllUsers();
    }
}

现在启动项目,你会看到控制台输出:

启动时加载用户数据到缓存...
正在从数据库查询用户数据...

这说明启动时已经调用了DAO,把数据存进缓存了。

然后你多次访问http://localhost:8080/users,控制台不会再输出“正在从数据库查询用户数据...”,说明每次都是直接从缓存拿数据,完美实现需求!

新手小提醒
  • @Cacheable的value必须和配置文件里的cache-names对应,不然Spring找不到对应的缓存
  • 如果你的方法有参数,缓存默认会用参数作为key,比如getUserById(Long id),不同的id会存在不同的缓存条目里
  • 如果数据库数据更新了,你需要用@CacheEvict(清除缓存)或者@CachePut(更新缓存)来同步缓存数据,不然会读到旧数据(这个咱们以后再慢慢研究,先搞定当前需求就好)

内容的提问来源于stack exchange,提问作者ulagan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:28:19