Spring Boot集成
2026/1/15大约 3 分钟JavaCaffeine缓存本地缓存后端
Spring Boot集成
Spring Cache 简介
Spring Cache 是 Spring 提供的缓存抽象层,通过注解方式简化缓存操作。Spring Boot 2.x 默认使用 Caffeine 作为缓存实现。
快速集成
1. 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>2. 启用缓存
@SpringBootApplication
@EnableCaching // 启用缓存
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}3. 配置缓存
# application.yml
spring:
cache:
type: caffeine
caffeine:
spec: maximumSize=10000,expireAfterWrite=10m4. 使用缓存注解
@Service
public class UserService {
@Cacheable(value = "users", key = "#id")
public User getById(Long id) {
// 缓存未命中时执行
return userRepository.findById(id).orElse(null);
}
@CachePut(value = "users", key = "#user.id")
public User update(User user) {
// 更新数据库并更新缓存
return userRepository.save(user);
}
@CacheEvict(value = "users", key = "#id")
public void delete(Long id) {
// 删除数据库并清除缓存
userRepository.deleteById(id);
}
}缓存注解详解
@Cacheable - 查询缓存
@Cacheable(
value = "users", // 缓存名称
key = "#id", // 缓存 key
condition = "#id > 0", // 缓存条件
unless = "#result == null" // 排除条件
)
public User getById(Long id) {
return userRepository.findById(id).orElse(null);
}@CachePut - 更新缓存
@CachePut(value = "users", key = "#user.id")
public User update(User user) {
return userRepository.save(user);
}@CacheEvict - 删除缓存
// 删除单个
@CacheEvict(value = "users", key = "#id")
public void delete(Long id) {
userRepository.deleteById(id);
}
// 删除所有
@CacheEvict(value = "users", allEntries = true)
public void deleteAll() {
userRepository.deleteAll();
}
// 方法执行前删除
@CacheEvict(value = "users", key = "#id", beforeInvocation = true)
public void deleteBeforeInvocation(Long id) {
userRepository.deleteById(id);
}@Caching - 组合注解
@Caching(
cacheable = {
@Cacheable(value = "users", key = "#id")
},
evict = {
@CacheEvict(value = "userList", allEntries = true)
}
)
public User getById(Long id) {
return userRepository.findById(id).orElse(null);
}@CacheConfig - 类级别配置
@Service
@CacheConfig(cacheNames = "users") // 类级别缓存名称
public class UserService {
@Cacheable(key = "#id") // 不需要再指定 value
public User getById(Long id) {
return userRepository.findById(id).orElse(null);
}
}自定义 CacheManager
单一缓存配置
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
.maximumSize(10000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.recordStats());
return cacheManager;
}
}多缓存配置
不同业务使用不同的缓存配置:
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
List<CaffeineCache> caches = new ArrayList<>();
// 用户缓存:容量大,过期时间长
caches.add(new CaffeineCache("users",
Caffeine.newBuilder()
.maximumSize(10000)
.expireAfterWrite(30, TimeUnit.MINUTES)
.recordStats()
.build()));
// 配置缓存:容量小,过期时间短
caches.add(new CaffeineCache("configs",
Caffeine.newBuilder()
.maximumSize(100)
.expireAfterWrite(5, TimeUnit.MINUTES)
.recordStats()
.build()));
// 热点缓存:容量中等,访问后过期
caches.add(new CaffeineCache("hotData",
Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterAccess(10, TimeUnit.MINUTES)
.recordStats()
.build()));
cacheManager.setCaches(caches);
return cacheManager;
}
}配置文件方式
@Configuration
@EnableCaching
public class CacheConfig {
@Value("${cache.users.max-size:10000}")
private int usersMaxSize;
@Value("${cache.users.expire-minutes:30}")
private int usersExpireMinutes;
@Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
List<CaffeineCache> caches = new ArrayList<>();
caches.add(new CaffeineCache("users",
Caffeine.newBuilder()
.maximumSize(usersMaxSize)
.expireAfterWrite(usersExpireMinutes, TimeUnit.MINUTES)
.build()));
cacheManager.setCaches(caches);
return cacheManager;
}
}# application.yml
cache:
users:
max-size: 10000
expire-minutes: 30缓存 Key 生成
SpEL 表达式
// 使用参数
@Cacheable(value = "users", key = "#id")
// 使用对象属性
@Cacheable(value = "users", key = "#user.id")
// 组合 key
@Cacheable(value = "users", key = "#type + ':' + #id")
// 使用方法
@Cacheable(value = "users", key = "#id.toString()")
// 使用 root 对象
@Cacheable(value = "users", key = "#root.methodName + ':' + #id")自定义 KeyGenerator
@Configuration
public class CacheConfig {
@Bean
public KeyGenerator customKeyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getSimpleName());
sb.append(":");
sb.append(method.getName());
sb.append(":");
for (Object param : params) {
sb.append(param.toString());
sb.append("_");
}
return sb.toString();
};
}
}
// 使用
@Cacheable(value = "users", keyGenerator = "customKeyGenerator")
public User getById(Long id) {
return userRepository.findById(id).orElse(null);
}缓存统计监控
暴露统计端点
@RestController
@RequestMapping("/cache")
public class CacheController {
@Autowired
private CacheManager cacheManager;
@GetMapping("/stats")
public Map<String, Object> stats() {
Map<String, Object> result = new HashMap<>();
cacheManager.getCacheNames().forEach(name -> {
Cache cache = cacheManager.getCache(name);
if (cache != null) {
com.github.benmanes.caffeine.cache.Cache<Object, Object> nativeCache =
(com.github.benmanes.caffeine.cache.Cache<Object, Object>) cache.getNativeCache();
CacheStats stats = nativeCache.stats();
Map<String, Object> cacheStats = new HashMap<>();
cacheStats.put("size", nativeCache.estimatedSize());
cacheStats.put("hitRate", stats.hitRate());
cacheStats.put("hitCount", stats.hitCount());
cacheStats.put("missCount", stats.missCount());
cacheStats.put("loadCount", stats.loadCount());
cacheStats.put("evictionCount", stats.evictionCount());
result.put(name, cacheStats);
}
});
return result;
}
@DeleteMapping("/{name}")
public void clearCache(@PathVariable String name) {
Cache cache = cacheManager.getCache(name);
if (cache != null) {
cache.clear();
}
}
}集成 Actuator
# application.yml
management:
endpoints:
web:
exposure:
include: caches,metrics@Configuration
public class CacheMetricsConfig {
@Bean
public MeterBinder caffeineCacheMetrics(CacheManager cacheManager) {
return registry -> {
cacheManager.getCacheNames().forEach(name -> {
Cache cache = cacheManager.getCache(name);
if (cache != null) {
com.github.benmanes.caffeine.cache.Cache<?, ?> nativeCache =
(com.github.benmanes.caffeine.cache.Cache<?, ?>) cache.getNativeCache();
CaffeineCacheMetrics.monitor(registry, nativeCache, name);
}
});
};
}
}小结
Spring Boot 与 Caffeine 的集成非常简单,通过 @EnableCaching 和缓存注解即可快速使用。对于复杂场景,可以自定义 CacheManager 配置不同的缓存策略。
面试题预览
常见面试题
- Spring Cache 的常用注解有哪些?
- 如何为不同业务配置不同的缓存策略?
- @Cacheable 的 condition 和 unless 有什么区别?
