缓存-Spring Cache 缓存抽象

缓存-Spring Cache 缓存抽象

Spring从版本3.1开始提供非侵入的将Cache集成到Spring应用的方式。Spring Cache提供Cache的统一抽象,支持集成各种不同的缓存解决方案。从4.1版本开始,提供了注解和更多的定制参数。

Spring Cache 抽象提供了对Java方法的缓存,使用Spring Cache缓存,当方法调用使用相同的参数,调用结果被缓存下来,当方法被再次调用时将直接返回参数结果。

关键类和接口

Cache

org.springframework.cache.Cache 提供Spring框架中使用的Cache的统一抽象功能, 具体的实现类使用实际的缓存解决方案。

  • NoOpCache: 空缓存,没有实际的缓存实现
  • EhCacheCache: 使用EhCache缓存方案。
  • CaffeineCache: 使用Java CaffeineCache。Caffeine提出了一种更高效的近似LFU准入策略的缓存结构TinyLFU及其变种W-TinyLFU,借鉴Guava Cache的设计经验,是一款功能强大,性能更优本地缓存。
  • JCacheCache: Javax Cache 标准接口,类似于Spring Cache的 JavaJ JSR缓存规范。
  • ConcurrentMapCache: 使用ConccrentMap的缓存实现。
  • TransactionAwareCacheDecorator: 识别Spring 事务的缓存实现装饰模式,只要当事务提交时才触发缓存的更新。

CacheManager

org.springframework.cache.CacheManager:Spring cache 管理API。不同的CacheManager实现提供对相应Cache实现缓存的管理,通过管理API Cache getCache(String name);方法对外提供。

CacheResolver

org.springframework.cache.interceptor.CacheResolver 方法调用拦截使用来获取Cache实现的Resolver,通常使用相应的CacheManager实现类来获取Cache。

KeyGenerator

org.springframework.cache.interceptor. KeyGenerator:缓存中Key的生成实现。默认的key生成器:org.springframework.cache.interceptor.SimpleKeyGenerator 类

  1. 方法没有参数则使用SimpleKey.EMPTY

  2. 方法只有一个参数:key=唯一参数

  3. 方法有多个参数:SimpleKey(params)

可以通过实现org.springframework.cache.interceptor.KeyGenerator接口定制key生成器。

使用Spring Cache

启用Spring Cache

@Configuration

@EnableCaching

注解使用

**@Cacheable:**作用于方法之上,配置方法缓存

@Cacheable("cacheName"): 指定用于缓存结果的缓存名称,当指定多个名称时,方法调用将在多个缓存中查找相同参数的方法调用,命中即返回。

Cache 的key

指定KeyGenerator:

@Cacheable(cacheNames="XXX", keyGenerator="myKeyGenerator")。

通过SpEL指定key

@Cacheable(cacheNames="books", key="#isbn")

public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

@CachePut: @CachePut指定的方法不影响方法的执行,方法执行结果将用于更新缓存。@CachePut支持同@Cacheable一样的配置。

示例:

@CachePut(cacheNames="book", key="#isbn")

public Book updateBook(ISBN isbn, BookDescriptor descriptor)

**@CacheEvict:**触发缓存清理陈旧或无用的数据。可以配置指定数据的清理或Cache范围的清理。

示例:

@CacheEvict(cacheNames="books", allEntries=true)

public void loadBooks(InputStream batch)

@Caching: 在一个方法上指定触发缓存的多个操作。

示例:

@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })

public Book importBooks(String deposit, Date date)

**@CacheConfig:**以上的注解都是方法级别的注解,@CacheConfig提供类级别的公共配置,该类下的方法级别配置如无指定则使用类级别上的@CacheConfig。

实现方式

Spring AOP

使用 Spring AOP切面实现Cache相关方法的拦截获取缓存和Cache请求的处理

  1. 配置切面: 所有所有类和所有方法都进行拦截

org.springframework.cache.interceptor.CacheProxyFactoryBean

相关代码:

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| private Pointcut pointcut = Pointcut.TRUE; protected Object createMainInterceptor() { this.cacheInterceptor.afterPropertiesSet(); return new DefaultPointcutAdvisor(this.pointcut, this.cacheInterceptor); } |

  1. org.springframework.cache.interceptor.CacheInterceptor 实现

org.springframework.cache.interceptor.MethodInterceptor接口,

CacheAspectSupport.execute方法是Spring Cache核心处理流程,下面是主要流程的部分代码解析:

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| // 处理CacheEvict请求 processCacheEvicts(contexts.get(CacheEvictOperation.class), true, CacheOperationExpressionEvaluator.NO_RESULT); // 从缓存中查询是否存在缓存 Cache.ValueWrapper cacheHit = findCachedItem(contexts.get(CacheableOperation.class)); // 如未命中,生成CachePut请求:缓存条件满足 List<CachePutRequest> cachePutRequests = new ArrayList<>(); if (cacheHit == null) { collectPutRequests(contexts.get(CacheableOperation.class), CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests); } Object cacheValue; Object returnValue; if (cacheHit != null && !hasCachePut(contexts)) { // 缓存命中,并且没有Put需求,返回缓存值 cacheValue = cacheHit.get(); returnValue = wrapCacheValue(method, cacheValue); } else { // 未命中,调用对象,获取可缓存值 returnValue = invokeOperation(invoker); cacheValue = unwrapReturnValue(returnValue); } // 检查是否存在CachePut请求 collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests); // 缓存更新 for (CachePutRequest cachePutRequest : cachePutRequests) { cachePutRequest.apply(cacheValue); } // 处理缓存Evicts请求 rocessCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue); return returnValue; } |

相关推荐
学长毕设11 小时前
基于SpringBoot的野生动物公益保护平台设计与实现-附源码
java·spring boot·后端
梦里寻码11 小时前
我用 NestJS + Vue3 写了一套完整的研发管理系统(58 表 / 229 API / 130 项断言,全开源
前端·后端·算法
鶴哥只手遮天11 小时前
《Redis 8.10.3 深度剖析》系列 ·第 10 章 Hash 一:`listpack`、`hashtable` 与 `LISTPACK_EX`
redis·后端·开源
SL_staff11 小时前
离散制造排程破局:JVS-APS 四步闭环落地实践(开发者视角)
java·产品·全栈
johnjincaaaa11 小时前
WebAssembly 逆向实战:从 0 搞懂猿人学第 15 题
后端
Gopher_HBo11 小时前
Go CPU 剖析:四角色白话机制 + 实测实验
后端
这个昵称不容易11 小时前
SpringBoot 美容院管理系统:232个Java文件315个接口,5套角色从预约到发货一整条链路
java·springboot·毕设
猿人谷11 小时前
Surrogate Model:让进化算法学会“预测”,为什么它正在成为智能优化的重要技术?
后端·算法·架构
装不满的克莱因瓶12 小时前
【SpringAI Alibaba】ReactAgent记忆管理MessageTrimmingHook与MessageDeletionHook
java·人工智能·ai·ai编程·springai·springaialibaba
the局外人12 小时前
LangChain ToolRuntime 入门:context、state 与 store 的实际用法
后端·langchain·agent