导读:本期聚焦于小伙伴创作的《Spring Boot 怎么整合 Spring Boot EnableCache 实现方法级缓存?》,敬请观看详情。方法级缓存能显著减少数据库压力,但不少人在接入时遇到注解不生效的问题。Spring Boot 通过 @EnableCaching 开启缓存抽象,配合 @Cacheable 等注解即可拦截方法返回值。底层依靠 AOP 代理,缓存管理器可切换为 Redis 或 Caffeine。配置时需保证启动类或配置类标注 EnableCaching,业务方法须由 Spring 容器管理且避免内部调用。本文梳理依赖引入、缓存管理器配置与常见失效原因,帮助构建稳定缓存层。

在 Spring Boot 应用中,方法级缓存是提升接口响应速度、降低数据库负载的重要手段。Spring 框架提供了一套统一的缓存抽象,开发者只需通过简单的注解就能让某个方法的返回结果自动存入缓存,下次相同参数调用时直接命中缓存而无需执行方法体。其中 @EnableCaching 是开启这套机制的钥匙,而具体的方法缓存控制则依赖 @Cacheable、@CachePut、@CacheEvict 等注解。

Spring Boot 怎么整合 Spring Boot EnableCache 实现方法级缓存?

一、基础整合步骤与依赖配置

要在 Spring Boot 中启用缓存支持,第一步是在项目的构建文件中引入相关依赖。如果仅使用本地内存缓存,引入 spring-boot-starter-cache 即可;若需要分布式缓存,通常还要加入 spring-boot-starter-data-redis。Spring Boot 的自动配置会依据 classpath 中的依赖尝试创建默认的缓存管理器,但显式声明配置能避免环境差异导致的意外行为。

引入依赖后,必须在配置类或主启动类上添加 @EnableCaching 注解。这个注解会向 Spring 容器注册一系列缓存相关的后置处理器,使得标注了缓存注解的 Bean 方法在运行时被 AOP 代理包裹。需要注意的是,@EnableCaching 本身不提供缓存存储实现,它只是打开缓存抽象的总开关,真正的存取逻辑由 CacheManager 及其底层的 Cache 实现完成。

下面是一个典型的 Maven 依赖配置和启动类示例。我们可以看到,启动类除了常规的 @SpringBootApplication 外,还叠加了 @EnableCaching,这样整个应用上下文中的缓存注解才会生效。如果遗漏该注解,即便方法上写了 @Cacheable,框架也会直接忽略,导致每次请求都穿透到数据库。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
@SpringBootApplication
@EnableCaching
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

二、缓存注解的使用与缓存管理器配置

开启 @EnableCaching 之后,就可以在业务层方法上使用 @Cacheable 注解。该注解的 value 或 cacheNames 属性用于指定缓存名称,key 属性支持 SpEL 表达式来动态生成缓存键。当方法被调用时,框架会先根据 key 查询缓存,若存在则直接返回缓存值,否则执行方法并将返回值写入缓存。类似地,@CachePut 用于更新缓存,@CacheEvict 用于删除缓存,三者组合可以实现完整的缓存生命周期管理。

默认情况下,Spring Boot 使用 ConcurrentMapCacheManager 作为内存缓存管理器,数据仅存在于单个应用实例的 JVM 堆中,重启即丢失,且无法在多节点间共享。在生产环境中,更常见的是配置 RedisCacheManager,将缓存集中存放在 Redis 中。通过自定义 RedisCacheConfiguration,我们还能设置默认的过期时间、键值序列化方式,从而避免乱码并控制缓存失效策略。

以下代码展示了如何通过 Java Config 显式配置一个带过期时间的 Redis 缓存管理器。这里设置了默认 TTL 为十分钟,并采用 String 序列化器处理键,Jackson 序列化器处理值。这种配置方式比单纯依赖自动配置更直观,也便于在多个缓存区域设置不同的过期策略。

@Configuration
public class CacheConfig {

    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(10))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        return RedisCacheManager.builder(factory).cacheDefaults(config).build();
    }
}

在业务代码中,使用注解的方式非常简洁。例如一个根据用户 ID 查询信息的接口,加上 @Cacheable 后,重复查询同一用户将不再访问数据库。但需特别注意,注解的方法必须是 public 且由 Spring 代理对象调用,类内部方法互调会造成代理失效,这是很多初学者容易踩的坑。

@Service
public class UserService {

    @Cacheable(value = "user", key = "#id")
    public User findById(Long id) {
        // 模拟数据库查询
        return userRepository.selectById(id);
    }
}

三、常见失效原因与性能优化思考

尽管 @EnableCaching 整合过程看似简单,但实际项目中常出现缓存不生效的情况。最常见的原因是内部调用:当一个 Bean 的方法 A 调用同一个 Bean 的 @Cacheable 方法 B 时,由于调用发生在对象内部而非通过 Spring 代理,AOP 拦截器不会被触发,缓存逻辑整体跳过。解决办法包括将方法拆分到不同 Bean,或通过获取代理对象自我调用。

另一个容易被忽略的点是 key 的生成策略。若未显式指定 key,Spring 会使用 SimpleKeyGenerator,将方法参数组合作为键。当方法有多个参数且包含不可序列化的对象时,可能导致 Redis 写入异常或键冲突。因此在复杂查询场景下,建议明确书写 key 表达式,如 key = "#user.name + '_' + #user.age",保证键的唯一与可读。

从性能角度考虑,方法级缓存虽好,但不应滥用。对于频繁变更的数据、实时性要求极高的接口,缓存可能带来数据不一致问题。此时可结合 @CacheEvict 在写操作后清理缓存,或采用更短的 TTL。此外,缓存穿透、击穿和雪崩也是生产必须面对的课题:可通过空值缓存防止穿透,用互斥锁或逻辑过期应对击穿,靠错峰过期时间缓解雪崩。只有将 @EnableCaching 的基础整合与这些工程化策略结合,才能构建出稳健高效的缓存层。

@CacheEvict(value = "user", key = "#id")
public void deleteUser(Long id) {
    userRepository.deleteById(id);
}

总体而言,Spring Boot 整合 @EnableCaching 并不复杂,难点在于理解其基于 AOP 的底层机制,并在分布式环境下选对 CacheManager 与序列化方案。当缓存注解与合理的配置、规范的调用方式配合时,系统吞吐量和响应延迟都会有肉眼可见的改善。

Spring_BootEnableCache方法级缓存修改时间:2026-08-15 20:18:16

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。