Spring 缓存抽象示例详解

时间:2022-11-18 11:02:32

spring缓存抽象概述

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