当前位置: 首页 > 编程笔记 >

Spring Cache的基本使用与实现原理详解

祁博涛
2023-03-14
本文向大家介绍Spring Cache的基本使用与实现原理详解,包括了Spring Cache的基本使用与实现原理详解的使用技巧和注意事项,需要的朋友参考一下

Spring Cache 概念

从Spring 3.1版本开始,提供了一种透明的方式来为现有的Spring 应用添加cache,使用起来就像@Transaction一样。在应用层面与后端存储之间,提供了一层抽象,这层抽象目的在于封装各种可插拔的后端存储( Ehcache Guava Redis),最小化因为缓存给现有业务代码带来的侵入。

Spring 的缓存技术还具备相当的灵活性。不仅能够使用 SpEL(Spring Expression Language)来定义缓存的 key 和各种 condition,还提供开箱即用的缓存暂时存储方案,也支持和主流的专业缓存比如 EHCache 集成。

其特点总结例如以下:

  • 通过少量的配置 annotation 凝视就可以使得既有代码支持缓存
  • 支持开箱即用 Out-Of-The-Box,即不用安装和部署额外第三方组件就可以使用缓存
  • 支持 Spring Express Language,能使用对象的不论什么属性或者方法来定义缓存的 key 和 condition
  • 支持 AspectJ,并通过事实上现不论什么方法的缓存支持
  • 支持自己定义 key 和自己定义缓存管理者,具有相当的灵活性和扩展性

设计理念

正如Spring框架的其它服务一样,Spring cache 首先是提供了一层抽象,核心抽象主要体现在两个接口上
org.springframework.cache.Cache

org.springframework.cache.CacheManager

Cache代表缓存本身

CacheManager代表对缓存的处理和管理等。抽象的意义在于屏蔽实现细节的差异和提供扩展性,这一层Cache的抽象解耦了缓存的使用和缓存的后端存储,这样后续可以方便的更换后端存储。

使用Spring Cache分三步:

  • 声明缓存
  • 开启Spring的cache功能
  • 配置后端的存储

声明缓存

@Cacheable("books")
public Book findBook(ISBN isbn) {...}

用法很简单,在方法上添加@cacheable等注解,表示缓存该方法的结果。

当方法有被调用时,先检查cache中有没有针对该方法相同参数的调用发生过,如果有,从cache中查询并返回结果。如果没有,则执行具体的方法逻辑,并把结果缓存到cache中。当然这一系列逻辑对于调用者来说都是透明的。其它的缓存操作的注解包含如下(详细说明可参见官方文档):

  • @Cacheable triggers cache population
  • @CacheEvict triggers cache eviction
  • @CachePut updates the cache without interfering with the method execution
  • @Caching regroups multiple cache operations to be applied on a method
  • @CacheConfig shares some common cache-related settings at class-level

开启Spring Cache的支持

<cache:annotation-driven />

或者使用注解@EnableCaching的方式

配置缓存后端存储

Spring Cache提供了几种内置的后端存储的实现:下面都是CacheManager的具体实现。

此外,Spring Data提供了两个缓存管理器:

  • RedisCacheManager(来自于Spring Data Redis项目)
  • GmfireCacheManager(来自于Spring Data GemFire项目

假如使用memcached或者redis等分布式缓存的话,可以自己实现Cache和CacheManager,然后在Context里声明即可。如果需要使用到多种不同的缓存实现,可以用组合模式把各种不同的CacheManager封装在一起。

缓存的key是如何生成

我们都知道缓存的存储方式一般是key value的方式,那么在Spring cache里,key是如何被设置的呢,在这里要引入KeyGenerator,它负责key的生成策略,默认的使用SimpleKeyGenerator


能看出来,其中就是有序参数数组的hash值。当然用户可以自定义key生成策略。

Spring Cache的实现

上面是Spring cache的大致使用方式,来看是Spring是如何实现的。

在学习Spring源码的时候,有两点可以记住:

  • 大多数高级功能的实现都依赖Spring AOP
  • 大多数功能的组装时机都依赖Sprin bean生命周期中的几个回调接口

记住了这些就比较容易理解Spring中的一些组件的实现及运行时机制

Spring cache也不例外,它是典型的Spring AOP实现,在Spring里,aop可以简单的理解为代理(AspectJ除外),我们声明了@Cacheable的方法的类,都会被代理,在代理中,实现缓存的查询与设置操作。

Cache 基础设施的创建

上一篇(Spring AOP 模块概述)谈到过,Spring AOP的创建过程,本质是实现了一个BeanPostProcessor,在创建bean的过程中创建proxy,并且为proxy绑定所有适用于该bean的advisor,最终暴露给容器。

Spring中AOP主几个关键的概念 advisor  advice pointcut

advice = 切面拦截中插入的行为

pointcut = 切面的切入点

advisor = advice + pointcut

Spring cache也同样与其它aop有类似的过程

创建 cache proxy

  • 由InfrastructureAdvisorAutoProxyCreator负责的,它实现BeanPostProcessor所以可以在bean实例化返回给容器前有机会创建代理,它又继承了AbstractAdvisorAutoProxyCreator,所以又具备了给代理类绑定advisor的能力。
  • pointcut的职责是由CacheOperationSourcePointcut完成的,它主要是通过方法上的cache相关的注解来判断匹配是否需要切入

Cache的拦截行

Spring cache中生成cache代理对象使用的是CacheProxyFactoryBean工厂类。一般来说,在Spring中标准代理的创建都是基于ProxyFactoryBean,在这里,为了更方便的处理cache逻辑,Spring引入了CacheProxyFactoryBean来专门表示cache相关的代理,cache proxy能wrapper单例目标对象,并且代理目标对象实现的所有接口。

可以看到,在CacheProxyFactoryBean中,有个重要的属性是CacheInterceptor,这个类是一个MethodInterceptor的实现类,这个类的职责是在目标对象目标方法上执行具体缓存操作,这也就是上面提到的advice的职责。

继续往下跟,return 的execute方法是父类CacheAspectSupport中的方法


在这个方法里,我们最终找到的操作缓存的最终逻辑

  • 判断缓存条件
  • 获取key
  • 获取cache
  • 最终调用cache.get(key, Callable)方法,第二个参数是一个回调,用于处理没有命中缓存的情况:
    if cached, return; otherwise create, cache and return

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对小牛知识库的支持。

 类似资料:
  • 本文向大家介绍详解SPA中前端路由基本原理与实现方式,包括了详解SPA中前端路由基本原理与实现方式的使用技巧和注意事项,需要的朋友参考一下 在讲前端路由之前,先说下后端路由,以及为什么出现了前端路由。 后端路由: 浏览器在地址栏中切换不同的url时,每次都向后台服务器发出请求,服务器响应请求,在后台拼接html文件传给前端显示,java web中的jsp就是如此实现的。常用的后台MVC模式的基本路

  • 本文向大家介绍go的websocket实现原理与用法详解,包括了go的websocket实现原理与用法详解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了go的websocket实现原理与用法。分享给大家供大家参考,具体如下: websocket分为握手和数据传输阶段,即进行了HTTP握手 + 双工的TCP连接 RFC协议文档在:http://tools.ietf.org/html/rfc

  • 本文向大家介绍详解@ConfigurationProperties实现原理与实战,包括了详解@ConfigurationProperties实现原理与实战的使用技巧和注意事项,需要的朋友参考一下 在SpringBoot中,当需要获取到配置文件数据时,除了可以用Spring自带的@Value注解外,SpringBoot提供了一种更加方便的方式:@ConfigurationProperties。只要在

  • 本文向大家介绍Python函数基本使用原理详解,包括了Python函数基本使用原理详解的使用技巧和注意事项,需要的朋友参考一下 1.什么是函数 函数就相当于具备某一功能的工具 函数的使用必须遵循一个原则: 先定义 后调用 2.为何要用函数 1、组织结构不清晰,可读性差 2、代码冗余 3、可维护性、扩展性差 3、如何用函数 1.函数的定义 定义的语法 ''' def 函数名(参数1,参数2,...)

  • 本文向大家介绍详解Java回调的原理与实现,包括了详解Java回调的原理与实现的使用技巧和注意事项,需要的朋友参考一下 回调原本应该是一个非常简单的概念,但是可能因为平时只用系统为我们写好的回调的接口了,自己很少实现回调,所以在自己实现回调的时候还是有一点点晕的,现在写这篇文章记录一下,也和大家分享一下怎么写回调接口。 回调 回调的概念:举个例子就是,我们想要问别人一道题,我们把题跟对方说了一下,

  • 本文向大家介绍问题:SVM的作用,基本实现原理;相关面试题,主要包含被问及问题:SVM的作用,基本实现原理;时的应答技巧和注意事项,需要的朋友参考一下 参考回答: SVM可以用于解决二分类或者多分类问题,此处以二分类为例。SVM的目标是寻找一个最优化超平面在空间中分割两类数据,这个最优化超平面需要满足的条件是:离其最近的点到其的距离最大化,这些点被称为支持向量。 解析:建议练习推导SVM,从基本式