SpringBoot与缓存

一、JSR107

JSR是Java Specification Requests 的缩写 ,Java规范请求,故名思议提交Java规范,大家一同遵守这个规范的话,会让大家‘沟通’起来更加轻松, JSR-107呢就是关于如何使用缓存的规范。

Java Caching定义了5个核心接口,分别是CachingProvider,CacheManager,Cache,Entry和Expiry。

CachingProvider定义了创建、配置、获取和控制多个CacheManager。一个应用可以在运行期间访问多个CachingProvider。

CacheManager定义了创建、配置、获取、管理和控制多个唯一命名的Cache,这些Cache存在于CacheManager的上下文中。一个CacheManager仅被一个CachingProvider所拥有。

Cache是一个类似Map的数据结构并临时存储以Key为索引的值。一个Cache仅被一个CacheManager所拥有。

Entry是一个存储在Cache中的key-value对。

Expiry每一个存储在Cache中的条目有一个定义的有效期。一旦超过这个有效期,条目为过期的状态。一旦过期,条目将不可访问、更新和删除。缓存有效期可以通过ExpiryPolicy设置。

二、Spring缓存抽象

Spring从3.1开始定义了org.springframework.cache.Cache 和org.springframework.cache.CacheManager接口来统一不同的缓存技术; 并支持使用JCache(JSR-107)注解简化我们开发;

• Cache接口为缓存的组件规范定义,包含缓存的各种操作集合;

• Cache接口下Spring提供了各种xxxCache的实现;如RedisCache,EhCacheCache , ConcurrentMapCache等;

• 每次调用需要缓存功能的方法时,Spring会检查检查指定参数的指定的目标方法是否 已经被调用过;如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法 并缓存结果后返回给用户。下次调用直接从缓存中获取。

• 使用Spring缓存抽象时我们需要关注以下两点;
1、确定方法需要被缓存以及他们的缓存策略
2、从缓存中读取之前缓存存储的数据

三、缓存注解

Cache缓存接口,定义缓存操作。实现有:RedisCache、EhCacheCache、 ConcurrentMapCache等 CacheManager 缓存管理器,管理各种缓存(Cache)组件
@Cacheable主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
@CacheEvict清空缓存
@CachePut保证方法被调用,又希望结果被缓存。
@EnableCaching开启基于注解的缓存
keyGenerator缓存数据时key生成策略
serialize缓存数据时value序列化策略

四、@Cacheable、@CachePut和@CacheEvict注解的主要参数

value缓存的名称,必须指定至少一个例如:@Cacheable(value=“mycache”)或者@Cacheable(value={“cache1”,“cache2”})
key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的 所有参数进行组合例如: @Cacheable(value=”mycache”,key=”#userName”)
condition缓存的条件,可以为空,使用 SpEL 编写,返 回 true 或者 false,只有为 true 才进行缓存/清 除缓存例如: @Cacheable(value=”testcache”,condition=”#userNam e.length()>2”)
allEntries (@CacheEvict )是否清空所有缓存内容,缺省为 false,如果指 定为 true,则方法调用后将立即清空所有缓存例如: @CachEvict(value=”testcache”,allEntries=true)
beforeInvocation (@CacheEvict)是否在方法执行前就清空,缺省为 false,如果 指定为 true,则在方法还没有执行的时候就清 空缓存,缺省情况下,如果方法执行抛出异常, 则不会清空缓存例如: @CachEvict(value=”testcache”, beforeInvocation=true)

五、@Cacheable注解

要使@Cacheable注解生效要在配置类上加@EnableCaching注解
在这里插入图片描述
@Cacheable注解的作用是将方法的运行结构进行缓存,以后再要相同的数据,直接从缓存中拿,不用调用方法。

@Cacheable注解的几个属性
    cacheNames/value:指定缓存名字,CacheManager管理多个Cache组件,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一名字。
    key:缓存数据使用的key,可以用它来指定,默认是使用方法的参数值(支持SPEL表达式)。
    key="#id"效果 == "#root.args[0]" == "#a0"
    keyGenerator:key的生成器,可以自己指定key的生成器,keyGenerator/key:二选一。
    cacheManager:指定缓存管理器。
    cacheResolver:和cacheManager一样,二选一。
    condition:指定符合条件的情况下,才缓存,可以用SPEL表达式。
    unless:否定缓存,当unless指定的条件为true,方法的返回值就不会缓存,可以取到结果进行判断。
    sync:缓存是否使用异步模式,在改没事下,unless属性没用。

SPEL表达式能写的内容如下:

名字位置位置示例
methodName(方法名字)root Object当前被调用的方法名当前被调用的方法名
method(方法)root Object当前被调用的方法#root.method
target(目标对象)root Object当前被调用的目标对象#root.target
targetClass(目标对象类)root Object当前被调用的目标对象类#root.targetClass
args(参数列表)root Object当前被调用的方法的参数列表#root.args[0]
caches(缓存列表)root Object当前方法调用的缓存列表#root.cache[0].name
argument name(方法参数的名字)evaluation context方法参数的名字,可以直接#参数名#a0,#p0
resultevaluation context方法执行后的返回值(仅当方法执行后的判断有效,如"unless","cache put"的表达式"cache evict"的表达式beforeInvocation=false)#result

如下代码:在这里插入图片描述
当传入的id大于零时且返回结果不为空时,结果才会被缓存。

缓存原理:
在springboot中如果要看与Cache相关原理,肯定有xxxAutoConfiguraiot与之对应。
在这里插入图片描述
其中最重要的是为IOC容器中导入了CacheConfigurationImportSelector(缓存配置导入选择器)这个类。
在这里插入图片描述
这个类中有一个selectImports(AnnotationMetadata importingClassMetadata)方法,这个方法的作用就是为容器中导入缓存组件。我们可以打个断点看一下:
在这里插入图片描述
我们可以看到这个方法一共为容器中导入了11个缓存组件,但是这11个缓存组件不都是全部生效的,我们只需在配置文件中加上如下属性:
在这里插入图片描述
这个配置的作用就是让程序在控制台中打印出哪些组件生效,哪些组件不生效。
在这里插入图片描述
我们可以看到是SimpleCacheConfiguration这个缓存配置类生效。
在这里插入图片描述
我们可以看到SimpleCacheConfiguration为容器中导入了一个缓存管理器(ConcurrentMapCacheManager),ConcurrentMapCacheManager实现了CacheManager接口。
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
ConcurrentMapCacheManager中的getCache()方法是通过缓存的名字来得到缓存对象的,如果得到的换成对象为null,就调用createConcurrentMapCache(name)方法。
在这里插入图片描述
这个方法创建了一个ConcurrentMapCache类的对象,这个类实现了Cache接口,内部通过维护一个ConcurrentMap来实现数据的换成与读取。
在这里插入图片描述
@Cacheable注解的运行流程
运行流程:
1.方法运行之前,先去查询Cache,按照cacheNames指定的名字获取(CacheManager先获取相应的缓存),第一次获取缓存,如果没有Cache组件会自动创建。
2.去Cache中查找缓存的内容,使用key,默认使用方法的参数
3.没有查询到缓存就调用目标方法,
4.将目标方法返回的结果,放进缓存里面
那为什么默认是使用方法的参数呢?它默认是使用SimpleKeyGenerator类的generate(Object target, Method method, Object… params) 来生成key。
方法中的第一个参数是目标对象,第二个参数是目标方法,第三个参数是目标方法的参数列表。
在这里插入图片描述

六、@CachePut注解

@CachePut: 既调用方法,又更新缓存数据
修改了数据库的某个数据,同时更新缓存

运行时机:
1.先调用目标方法
2.将目标方法的结果缓存起来
如下图:
在这里插入图片描述

七、@CachePut注解

@CacheEvict:缓存清除
key:指定要清除的数据
allEntries=true:指定清除这个缓存中的所有数据
beforeInvocation=true:表示在方法执行之前执行缓存清除。beforeInvocation=false情况下,如果方法出错,那么缓存就不会清除,beforeInvocation=true情况下,那么缓存就会清除
在这里插入图片描述

八、@Cachingt注解

@Caching是一个组合注解
在这里插入图片描述
在这里插入图片描述

九、@CacheConfig注解

@CacheConfig注解里面的属性

cacheNames:指定公共的缓存名字,这样就不需要再@Cacheable@CachePut@CacheEvict等注解里面指定cacheNames属性
keyGenerator:指定公共的key生成器
cacheManager:指定公共的缓存管理器
cacheResolver:指定公共的缓存解析器

在这里插入图片描述

十、SpringBoot整合Redis

可以看我的另一篇文章SpringBoot整合Redis

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值