spring框架自身并没有实现缓存解决方案,但是从3.1开始定义了org.springframework.cache.cache和org.springframework.cache.cachemanager接口,提供对缓存功能的声明,能够与多种流行的缓存实现集成。
cache接口为缓存的组件规范定义,包含缓存的各种操作集合;
cache接口下spring提供了各种xxxcache的实现:如rediscache,ehcachecache , concurrentmapcache等;
cachemanager接口为缓存管理器规范,简单来说就是用于存放cache,spring默认也提供了一些列管理器的实现。
spring缓存抽象提供了5个注解用来声明缓存规则:
@cacheable:能够根据方法的请求参数对其结果进行缓存,多用于查询
@cacheput: 执行方法,并缓存结果
@cacheevict:清空缓存
@caching:能够同时应用多个缓存注解功能
@cacheconfig: 用于抽取缓存的公共配置(类级别)
以上5个注解除了@cacheconfig注解是类级别的注解,其余4个注解在类和方法上均可以使用,作用在类上表示对该类下所有方法生效,作用的方法上只对该方法生效,且只能用于public修饰的符方法,protected或者private修饰的方法不适用。
@cacheable注解
@cacheable注解的作用是spring在调用该方法之前,首先在缓存中查找方法的返回值,默认的key是根据参数值生成,如果存在,直接返回缓存中的值,否则执行该方法,并将返回值保存到缓存中
@cacheable运行流程:
1.方法运行之前,先去查询cache(缓存组件),按照cachenames指定的名字获取;
(cachemanager先获取相应的缓存),第一次获取缓存如果没有cache组件会自动创建。
2.去cache中查找缓存的内容,使用一个key,默认就是方法的参数值;
key是按照某种策略生成的;默认是使用keygenerator生成的,
spring默认加载的是simplecachemanage,simplekeygenerator生成key的默认策略是:
如果没有参数;key=new simplekey()
如果有一个参数:key=参数的值
如果有多个参数:key=new simplekey(params)
3.没有查到缓存就调用目标方法;
4.将目标方法返回的结果,放进缓存中
@cacheable属性说明:
1.achenames/value:该属性值必须提供,指定缓存组件的名字,将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存;
如:cachenames = "product"或者cachenames = {"product1","product2"}
2.key:缓存数据使用的key,不指定key则默认是使用方法参数的值该属性值支持spel表达式
3.cachemanager:指定缓存管理器;或者cacheresolver指定获取解析器
4.condition:指定符合条件的情况下才缓存
5.unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断
unless = "#result == null"
unless = "#a0==2":如果第一个参数的值是2,结果不缓存;
6.sync:是否使用异步模式
使用示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@cacheable (cachenames = "product" ) // 默认key为参数,多个参数simplekey [arg1,arg2]
//@cacheable(cachenames = "product",key = "#root.methodname+'['+#id+']'")
//@cacheable(cachenames = "product",keygenerator = "mykeygenerator")
//@cacheable(cachenames = "product",key = "#root.methodname+'['+#id+']'",condition="#a0>10",unless = "#a0==11") //带条件的缓存满足condition=true缓存,满足unless=true则不缓存
public product getproductbyid( long id){
product product =productmapper.getproductbyid(id);
system.out.println(product);
return product;
}
//指定key属性值
@cacheable (cachenames = "product" , key= "#id" ) //”#+参数名”的形式,直接使用参数名
//或者
//@cacheable(cachenames ="product", key="#a0") //”#a+参数位置”的形式
public product getproductbyid( long id) {
xxxx
}
@cacheable (cachenames = "product" , key= "# productcondition.productid" )
//或者
//@cacheable(cachenames ="product", key="#a0.productid")
public product getproduct (product productcondition) {
xxxx
}
|
自定义key生成器
除了通过spel表达式之外,还可以通过自定义key生成器的方式,spring缓存模块提供了org.springframework.cache.interceptor.keygenerator
接口用于缓存key的生成声明,因此我们可以自定义一个mykeygenerator类并实现了keygenerator接口 ,使用如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
@configuration
public class mycacheconfig {
@bean ( "mykeygenerator" )
public keygenerator keygenerator(){
return new keygenerator(){
@override
public object generate(object target, method method, object... params) {
return method.getname()+ "[" + arrays.aslist(params).tostring()+ "]" ;
}
};
}
}
|
该方法测试用,关于缓存key的生成方式,网上有很多种策略。
使用时只需要修改注解的key属性即可:
1
|
@cacheable (cachenames = "product" ,keygenerator = "mykeygenerator" )
|
@cacheput
@cacheput注解的作用简单的说一句话:既调用方法,又缓存数据。@cacheput和@cacheable两个注解都可以用于填充缓存,但使用上略有点差异,@cacheable注解的执行流程是先在按key在缓存中查找,存在则返回,不存在则执行目标方法,并缓存目标方法的结果。而@cacheput并不会检查缓存,总是先执行目标方法,并将目标方法的结果保存到缓存中。实际中比如执行到更新操作时,则希望将最新的数据更新到缓存,如果该方法返回异常,将不再执行保存缓存的逻辑。
@cacheput属性说明
@cacheput注解属性与@cacheput类似,并没有增加其他属性
使用示例:
1
2
3
4
5
6
7
8
9
10
|
@cacheput (value= "product" ,key = "#result.productid" ,condition = "#result!=null" )
public product updateproduct(product product){
int count = productmapper.updateproduct(product);
system.out.println( "影响行数:" +count);
if (count> 0 ){
return product;
} else {
return null ;
}
}
|
@cacheevict注解
该注解的作用根据指定的key或者是allentries属性值移除缓存中特性的键值对。
@cacheevict属性说明
与@cacheable相比@cacheevict注解提供了另外两个属性:
1.allentries:表示是否清空所有缓存内容,默认false,如果该值为true则清空指定cachenames缓存块下所有内容,如果指定了allentries为true,那么再zhidingkey值将没有意义
2.beforeinvocation:是否在执行方法前请空缓存,默认值为false,如果该值为true则在调用目标方法前执行清空缓存,为false的情况下,如果目标方法抛出异常,则不再执行清空缓存逻辑
示例:
1
2
3
4
5
6
7
|
//@cacheevict(value="product",key="#id")
//@cacheevict(value="product",allentries = true) //清楚所有缓存
@cacheevict (value= "product" ,allentries = true ,beforeinvocation = true ) //清楚所有缓存
public boolean deleteproductbyid( long id) {
productmapper.deleteproductbyid(id);
return true ;
}
|
@caching注解
该注解是一个分组注解,作用是可以同时应用多个其他注解,该注解提供了3个属性cacheable,put,evict分别用于组合@cacheable、@cacheput、@cacheevict三个注解
使用示例:
1
2
3
4
5
6
7
8
9
10
11
|
@caching (
cacheable = { @cacheable (value= "product" ,key= "#productname" )},
put = {
@cacheput (value= "product" ,key= "#result.productid" ),
@cacheput (value= "product" ,key= "#result.productname" )
}
)
public product getproductbyname(string productname){
product product =productmapper.getproductbyname(productname);
return product;
}
|
当@cacheing同时含有cacheput注解和cacheable注解时,仍然会先执行目标方法。(并不是按@cacheable的执行过程,先检查缓存,存在则返回)
@cacheconfig
是一个类级别的注解,允许共享缓存的名称、keygenerator、cachemanager 和cacheresolver
示例:
1
2
3
4
|
@service
@cacheconfig (cachenames = "product" )
public class productservice {
}
|
在类上使用该注解,指定cachenames属性值,则类中方法上的注解将默认继承了该属性值,如果方法上注解使用和了@cacheconfig向同的属性,则以方法上的为准。
1
2
3
4
5
6
7
8
9
10
11
12
|
@service
@cacheconfig (cachenames = "product" )
public class productservice {
@autowired
private productmapper productmapper;
@cacheable (cachenames = "product1" ,key = "#root.methodname+'['+#id+']'" )
public product getproductbyid( long id){
product product =productmapper.getproductbyid(id);
system.out.println(product);
return product;
}
}
|
上面@cacheable和@cacheconfig都指定了属性值cacaenames,实际以方法上注解指定的为准。
spring缓存抽象的关键原理就是使用spring aop,通过切面实现了在方法调用前、调用后获取方法的入参和返回值,进而实现了缓存的逻辑。
总结
以上所述是小编给大家介绍的spring 缓存抽象示例详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
原文链接:https://www.cnblogs.com/ashleyboy/p/9591604.html