基于Spring Boot的Java应用如何实现服务层方法的缓存功能?
Spring Boot 服务层缓存实现方案
你使用Spring Boot开发时直接参考文档中Spring Boot相关配置章节即可,原生Spring的手动配置部分可以完全跳过,Spring Boot的自动装配已经完成了缓存管理器、AOP切面等基础组件的注册。@Cacheable完全适配你的场景:该注解作用于查询类方法时,会先根据入参查缓存,缓存存在直接返回结果,不存在就执行方法逻辑并将返回值写入缓存。SimpleCacheCustomizer只要放在能被Spring扫描到的配置类中即可,通常推荐放在项目根路径下的config包中,和其他自定义配置类统一管理,不要和业务代码混放。
以下是完整的实现示例:
步骤1:引入缓存依赖
在pom.xml中添加Spring Boot缓存启动器:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
生产环境推荐额外引入Caffeine缓存依赖(比默认ConcurrentMap缓存性能更高,支持过期、容量限制等特性),Spring Boot会自动适配不需要额外配置:
<dependency> <groupId>com.github.benmanes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency>
步骤2:开启缓存功能
在项目启动类上加@EnableCaching注解开启缓存自动配置:
@SpringBootApplication @EnableCaching // 开启缓存能力 public class YourProjectApplication { public static void main(String[] args) { SpringApplication.run(YourProjectApplication.class, args); } }
步骤3:给目标方法加缓存注解
直接在findAllByCountry方法上加@Cacheable即可,原有业务逻辑不需要修改:
@Override // value为缓存分区名,key用Country的唯一标识生成,避免全对象序列化开销 @Cacheable(value = "employeeByCountryCache", key = "#country.id") public List<EmployeeDTO> findAllByCountry(Country country) { final Map<Pair<UUID, String>, List<CountryTranslatable>> valueList = countryRepository... // 原有业务逻辑保持不变 }
注意:如果用Country对象作为默认key生成规则的入参,需要确保Country类实现了Serializable接口,否则会序列化报错。
步骤4:(可选)自定义缓存配置
在config包下新建缓存配置类,添加SimpleCacheCustomizer自定义缓存行为:
package com.yourproject.config; import org.springframework.boot.autoconfigure.cache.SimpleCacheCustomizer; import org.springframework.cache.caffeine.CaffeineCache; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.github.benmanes.caffeine.cache.Caffeine; import java.util.concurrent.TimeUnit; @Configuration public class CacheConfig { // 针对默认ConcurrentMap缓存的自定义配置 @Bean public SimpleCacheCustomizer simpleCacheCustomizer() { return cacheManager -> { // 可针对指定缓存分区设置规则,比如禁止缓存空值 CaffeineCache cache = (CaffeineCache) cacheManager.getCache("employeeByCountryCache"); if (cache != null) { cache.setAllowNullValues(false); } }; } // 如果用Caffeine缓存,可自定义全局过期、容量规则 @Bean public Caffeine<Object, Object> caffeineConfig() { return Caffeine.newBuilder() .expireAfterWrite(30, TimeUnit.MINUTES) // 写入后30分钟过期 .maximumSize(1000); // 单分区最大缓存1000条数据 } }
注意事项
- 同个类内部调用加了缓存注解的方法会失效,原因是Spring AOP的代理机制,跨类调用才会触发缓存逻辑
- 员工数据、国家数据更新时,需要配合
@CacheEvict注解主动清理对应缓存,避免出现脏数据 - 分布式部署场景下需要换成Redis等分布式缓存实现,Spring Boot同样提供自动配置,只需要引入对应starter即可
内容的提问来源于stack exchange,提问作者user16409822
相关产品推荐
相关产品推荐

