本文主要是介绍使用Spring Cache本地缓存示例代码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《使用SpringCache本地缓存示例代码》缓存是提高应用程序性能的重要手段,通过将频繁访问的数据存储在内存中,可以减少数据库访问次数,从而加速数据读取,:本文主要介绍使用SpringCac...
一、Spring Cache简介
Spring Cache 是 Spring 框架提供的一套声明式缓存抽象层,通过注解方式简化缓存操作,它通过在方法上添加注解(如 @Cacheable、@CacheEvict
)来地管理缓存操作,无需手动编写缓存逻辑。
它支持多种缓存实现(如 Caffeine、Redis、EhCache),并统一了缓存访问的 API。
这里需要注意两点:
- Spring Cache 只是一个声明式的抽象缓存层,意思是它只提供了接口,不提供实现
- 具体的实现可以有很多,比如 Caffeine,Redis,EhCache 这些,只要实现了这些接口,就可以被 Spring Cache 使用。
核心特点:
- 基于注解的声明式缓存
- 支持 SpEL 表达式
- 自动与 Spring 生态集成
- 支持条件缓存
二、基础配置
1. 添加依赖
<!-- Spring Boot Cache Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <!-- 如果使用Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- 如果使用caffeine --> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency>
2. 启用缓存
在启动类添加@EnableCaching
注解:
@SpringBootApplication @EnableCaching public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } }
3. 缓存配置方案
方案1:通过 yml 配置文件
spring: cache: type: caffeine caffeine: spec: maximumSize=500,expireAfterWrite=60s # 或者分开配置 cache-names: users,products caffeine.spec: # 全局默认配置 maximumSize=1000, expireAfterAccess=30m
方案2:自定义 Bean
@Configuration // 标记这是一个Spring配置类 public class CacheConfig China编程{ /** * 创建并配置Caffeine缓存管理器 * * @return CacheManager 实例,用于管理www.chinasem.cn应用中所有缓存 * * 主要配置参数说明: * - initialCapacity: 初始缓存空间大小(提升初始性能) * - maximumSize: 缓存最大容量(基于条目数) * - expireAfterWrite: 写入后过期时间(数据一致性优先场景) * - recordStats: 开启统计功能(用于监控和调优) */ @Bean public CacheManager cacheManager() { // 创建Caffeine缓存管理器实例 CaffeineCacheManager cacheManager = new CaffeineCacheManager(); // 配置Caffeine缓存参数 cacheManager.setCaffeine(Caffeine.newBuilder() .initialCapacity(100) // 初始容量100个条目 .maximumSize(1000) // 最大缓存1000个条目,超过后按LRU淘汰 .expireAfterWrite(10, TimeUnit.MINUTES) // 写入10分钟后过期 .recordStats()); // 启用缓存统计(命中率等) return cacheManager; } /** * 创建短期缓存实例(独立于主缓存管理器) * * @return Cache 实例,适用于高频访问的临时数据 * * 典型使用场景: * - 高频访问的临时数据 * - 需要快速失效的验证码等 * - 与其他缓存不同生命周期的数据 */ @Bean(name = "shortTermCache") // 指定Bean名称便于按名称注入 public Cache shortTermCache() { return Caffeine.newBuilder() .expireAfterWrite(1, TimeUnit.MINUTES) // 1分钟过期(短期存储) .maximumSize(100) // 最大100个条目 .build(); // 构建Cache实例 } }
三、 缓存注解使用示例
@Cacheable
:用于标记方法,表示该方法将结果缓存起来,下次调用时直接从缓存中获取结果,而不需要重新执行方法。@CacheEvict
:用于标记方法,表示该方法将清除缓存,通常用于删除缓存。@CachePut
:用于标记方法,表示该方法将更新缓存,通常用于更新缓存。@Caching
:用于组合多个缓存注解,可以同时使用多个缓存注解。@CacheConfig
:用于标记类,表示该类中的所有方法将使用指定的缓存配置。
1.@Cacheable - 数据查询缓存
/** * 根据ID获取用户信息(带缓存) * @param id 用户ID * @return 用户对象,如果不存在返回null * * @Cacheable 参数说明: * - value/cacheNames: 指定缓存名称(对应Caffeine配置) * - key: 缓存键,使用SpEL表达式(#参数名引用方法参数) * - unless: javascript条件表达式,当结果满足条件时不缓存 */ @Cacheable(value = "users", key = "#id", unless = "#result == null") public User getUserById(Long id) { log.info("执行数据库查询,用户ID: {}", id); return userRepository.findById(id).orElse(null); }
2.@CachePut - 更新数据并缓存
/** * 更新用户信息(同时更新缓存) * @param user 用户对象 * @return 更新后的用户对象 * * @CachePut 特点: * - 总是执行方法体 * - 用返回值更新缓存 * - 适用于"先写后读"场景 */ @CachePut(value = "users", key = "#user.id") public User updateUser(UChina编程ser user) { log.info("更新用户数据: {}", user.getId()); return userRepository.save(user); }
3.@CacheEvict - 删除缓存
/** * 删除用户(同时移除缓存) * @param id 用户ID * * @CacheEvict 参数说明: * - beforeInvocation: 是否在方法执行前清除缓存(默认false) * - allEntries: 是否清空整个缓存区域(慎用) */ @Cwww.chinasem.cnacheEvict(value = "users", key = "#id") public void deleteUser(Long id) { log.info("删除用户: {}", id); userRepository.deleteById(id); }
4. @Caching - 组合操作
组合操作允许在单个方法上同时使用多个缓存注解,以实现更复杂的缓存策略。
/** * 更新用户状态(复杂缓存操作) * @param userId 用户ID * @param status 新状态 * * 典型场景: * - 更新用户缓存 * - 同时失效用户列表缓存 */ @Caching( put = @CachePut(value = "users", key = "#userId"), evict = @CacheEvict(value = "userList", allEntries = true) ) public void updateUserStatus(Long userId, UserStatus status) { log.info("更新用户{}状态为{}", userId, status); userRepository.updateStatus(userId, status); }
5. 条件缓存 (condition/unless)
条件缓存允许在缓存注解中添加 SpEL 条件表达式,以控制缓存的触发时机。
/** * 获取用户详情(带条件缓存) * @param id 用户ID * * 缓存条件说明: * - condition: 只有id>1000时才走缓存 * - unless: 结果中status=DELETED时不缓存 */ @Cacheable(value = "users", key = "#id", condition = "#id > 1000", unless = "#result != null && #result.status == T(com.example.UserStatus).DELETED") public User getUserDetail(Long id) { log.info("查询用户详情: {}", id); return userRepository.findDetailById(id); }
6. 异步缓存加载
/** * 获取用户订单列表(异步缓存) * @param userId 用户ID * * @sync = true 表示: * - 多线程并发时,只有一个线程会执行加载 * - 其他线程等待结果 */ @Cacheable(value = "orders", key = "#userId", sync = true) public List<Order> getUserOrders(Long userId) { log.info("加载用户{}订单数据...", userId); return orderService.getOrdersByUser(userId); }
四、特殊场景处理
1. 缓存空值防御
/** * 查询用户(防穿透处理) * @param name 用户名 * * 特殊处理: * - 对null结果也进行缓存(特殊标记对象) * - 设置较短过期时间(配置文件中定义) */ @Cacheable(value = "usersByName", key = "#name", unless = "#result == null || #result == T(com.example.CacheConstants).NULL_OBJECT") public User getUserByName(String name) { User user = userRepository.findByName(name); return user != null ? user : CacheConstants.NULL_OBJECT; }
2. 复合缓存键
/** * 获取用户在某系统的权限列表 * @param userId 用户ID * @param systemCode 系统编码(如:"OA", "CRM"等) * @return 权限字符串集合 * * 缓存Key设计说明: * 1. 使用复合Key结构:`用户ID_系统编码`(如:123_OA) * 2. 优点: * - 避免不同系统权限缓存冲突 * - 支持按用户+系统维度独立管理缓存 * 3. 缓存条件:仅当结果非空时缓存 */ @Cacheable(value = "userPermissions", key = "#userId + '_' + #systemCode", unless = "#result == null || #result.isEmpty()") public Set<String> getUserSystemPermissions(Long userId, String systemCode) { log.debug("查询用户[{}]在系统[{}]的权限", userId, systemCode); return permissionService.findPermissions(userId, systemCode); } /** * 获取用户角色列表(带枚举参数的Key示例) * @param userId 用户ID * @param roleType 角色类型枚举 * * 枚举类型处理技巧: * 1. 调用枚举的name()方法转换为字符串 * 2. 最终Key格式:`userId:roleType`(如:123:ADMIN) */ @Cacheable(value = "userRoles", key = "#userId + ':' + #roleType.name()") public List<Role> getUserRoles(Long userId, RoleType roleType) { return roleService.findByUserAndType(userId, roleType); }
五、经验之谈
- 推荐为每个
@Cacheable
方法添加unless
条件防御null
值 - 业务更新方法建议同时使用
@CachePut
和@CacheEvict
- 高频访问数据考虑设置
sync=true
总结
到此这篇关于使用Spring Cache本地缓存的文章就介绍到这了,更多相关Spring Cache本地缓存内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!
这篇关于使用Spring Cache本地缓存示例代码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!