当前位置: 首页 > news >正文

缓存-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;

}

http://www.lryc.cn/news/223683.html

相关文章:

  • Java修仙传之神奇的ES2(巧妙的查询及结果处理篇)
  • 架构设计的课程资料
  • 数据结构与算法C语言版学习笔记(5)-串,匹配算法、KMP算法
  • 新版HI3559AV100开发注意事项
  • Django(一、简介,安装与使用)
  • 【Linux C IO多路复用】多用户聊天系统
  • JSON——数组语法
  • 运营商大数据精准获客:我们提供精准客源渠道的最大资源体?
  • 表象变换与矩阵元
  • vue乾坤微前端项目
  • 大语言模型比武
  • 王道数据结构第五章二叉树的遍历第13题
  • 微服务的发展历程的详细说明及每个阶段主流的架构和组件
  • 2023年眼镜行业分析(京东眼镜销量数据分析):市场规模同比增长26%,消费需求持续释放
  • 基础课26——业务流程分析方法论
  • 【数字图像处理-TUST】实验二-图像噪声生成与滤波降噪
  • bilibili快速升满级(使用Docker 容器脚本)
  • Android 13.0 Settings主页面去掉FocusRecyclerView相关功能
  • Python(四)字符串
  • WPF中ElementName与RelativeSource绑定的局限性以及对策
  • 基于PHP语言的会员系统搭建(Docker版)
  • 文件改名:一次性解决文件名混乱,批量重命名技巧
  • app自动化测试——capability 配置参数解析
  • 数仓面经大框架
  • C++ explicit关键字的作用
  • 排序算法之-冒泡
  • 【微服务】API治理发展历史与未来趋势
  • TikTok shop美国小店适合哪些人做?附常见运营问题解答
  • [OS]11.9.2023 中断
  • unity笔记