
Spring Cache
Spring提供了能够缓存方法调用结果的注解:@Cacheable,@CacheEvict,@CachePut,@Caching,@CacheConfig。
该注解可以用在任何方法中。
@Cacheable
使用
@Cacheable可以注解在需要缓存的方法上。
通过@Cacheable可以设定:
- 缓存使用的CacheName
- 缓存存放的key;
- 缓存的条件;
设定注解的value后,当方法被调用,Spring会把返回值存放在名为CacheName的缓存中,将参数Hash后的值作为key,返回值作为value。
当下次以相同参数调用方法时,Spring将从缓存中取出上次的结果,然后将结果返回,本次不调用该方法。
一个示例
1 |
|
1 |
|
在一次运行过程中,多次请求https://127.0.0.1/get?s=1,获取的结果都是一致的。
缓存中的key
缓存的实现本质是键值存储。
若方法没有参数,将以SimpleKey.EMPTY作为key将结果存放;
若方法有一个参数,则直接以这个参数作为key;
若方法有多个参数,则返回一个包含所有参数的SimpleKey。(hashCode()的结果)
若方法有多个参数,可以指定一个SpEL表达式作为SimpleKey进行存储。
1 |
|
无论b和c为多少,只有a改变时,缓存才会发生改变。
同步缓存
在多线程环境中,可能会有多个线程同时调用同一个方法;
默认缓存不锁定任何东西,可能会导致多次调用,然后达到同样的缓存结果。
对于这种情况,可以使用sync
属性;
添加该属性后,在多个线程调用方法时,只有一个线程用于计算,其他线程被阻塞直到缓存被更新。
1 |
|
条件缓存
可以设定达到指定的条件再进行缓存,使用参数condition
。使用SpEL表达式作为值。
根据参数进行条件缓存
condition
1 |
|
当s的值大于10,则进行缓存。
1 |
|
当字符串s长度大于3时进行缓存。
unless
unless发生在方法调用结束之后,也用来判断是否需要缓存,这个属性不会控制方法是否被调用。
unless的属性值表现方式与condition相反,译为“如果不”,则进行缓存。
可以使用#result
来代表返回的对象,填充属性值。
1 |
|
当方法调用返回的对象的id小于等于10,则返回缓存的结果,本地调用返回的结果丢弃。
反之,将本次调用的结果存到缓存中。
SpEL表达式可以用的元参数
Name | Location | Description | Example |
---|---|---|---|
methodName | Root object | 被调用的方法名 | #root.methodName |
method | Root object | 被调用的方法 | #root.method.name |
target | Root object | 被调用的目标对象 | #root.target |
targetClass | Root object | 目标对象的class | #root.targetClass |
args | Root object | 被调用的参数列表 | #root.args[0] |
caches | Root object | 当前方法调用使用的缓存列表。(如@Cacheable({“cache1”,“cache2”})) | #root.caches[0].name |
Argument name | Evaluation context | 方法参数的名字,使用#参数名 ,也可以使用#p0 或#a0 ,0代表参数的索引 | #apple #p0 #a1 |
result | Evaluation context | 方法执行后的返回值 | #result |
@CachePut
使用@CachePut注解的方法,方法总会被调用执行,并且会将调用结果放到缓存中。
@CacheEvict
使用@CacheEvict注解可以对缓存进行清理。
可以指定一个或多个缓存清理,允许指定key或条件进行缓存,另可以带一个参数allEntries
表示是否需要清理所有的缓存。
1 |
|
清理cacheNames为books的缓存。
@Caching
@Caching注解可以让多个相同的注解进行嵌套。
1 |
|
@CacheConfig
@CacheConfig注解用在类上,可以为整个类共享一个CacheName。
在方法上的@Cachable注解不需要添加CacheName属性,就可以实现缓存;
若类里面有一个方法的@Cachable注解有CacheName属性,则该方法使用自己的CacheName,不共享类的CacheName。
若方法没有被@Cachable注解,则不会进行缓存。
@EnableCaching
要使以上的注解生效,需要在启动类或配置类上添加@EnableCaching注解。