Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

Redis使用注解实现二级缓存

1、介绍

上一篇文章中,我们实现二级缓存的方式是通过java代码判断Redis是否存在缓存,然后决定从何处取数据,但是这种方法在我们有大量的需要用到缓存的地方的时候,会产生大量的冗余代码,而且有大量的判断语句,让我们的代码不能够专注于业务上面,这样子是不太好的。

所以在Spring的3.1版本之后就引入了对注解的支持,我们可以通过在类上、方法上标记注解来实现二级缓存的存取

其三个注解分别为:CacheableCacheEvictCachePut

下面我会将三个注解分别展开进行简单解释

2、Cacheable注解

  • @Cacheable可以标记在一个方法上,也可以标记在一个类上。
  • 对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。
  • Spring在缓存方法的返回值时是以键值对进行缓存的,值就是方法的返回结果。
  • 至于键的话,Spring又支持两种策略,默认策略和自定义策略,这个稍后会进行说明。
  • 需要注意的是当一个支持缓存的方法在对象内部被调用时是不会触发缓存功能的。
  • @Cacheable可以指定三个属性,value、key和condition。

2.1、value属性

value属性是必须指定的,其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称。其可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组。
如下例子所示:

1
2
3
4
5
6
@RequestMapping("selectForAll")
@Cacheable(value = "MYBATIS:com.chen.mysqlredisdemo.StudentMapper::AllStudent")
public List<Student> selectStudentForAll() {
List<Student> studentList = studentService.selectStudentForAll();
return studentList;
}

2.2、key属性

  • key属性是用来指定Spring缓存方法的返回结果时对应的key的。
  • 该属性支持SpringEL表达式。当我们没有指定该属性时,Spring将使用默认策略生成key。
  • 定义策略是指我们可以通过Spring的EL表达式来指定我们的key。这里的EL表达式可以使用方法参数及它们对应的属性。使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”。
    如下例子所示:
    1
    2
    3
    4
    5
    6
    @RequestMapping("/selectForOne/{sId}")
    @Cacheable(value = "MYBATIS:com.chen.mysqlredisdemo.StudentMapper", key = "#sId")
    public Student selectStudentForOne(@PathVariable int sId) {
    Student student = studentService.selectStudentForOne(sId);
    return student;
    }
    此时,如果我查询了一个sId为1800710318的学生
    那么上面的方法中最后缓存的键为:MYBATIS:com.chen.mysqlredisdemo.StudentMapper::1800710318

2.3、condition属性

  • condition属性可以用于指定缓存发生的条件。
  • 有的时候我们可能并不希望缓存一个方法所有的返回结果,这时候通过condition属性可以实现这一功能。
  • condition属性默认为空,表示将缓存所有的调用情形。
  • 其值是通过SpringEL表达式来指定的,当为true时表示进行缓存处理;当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次。
    如下例子所示:
    1
    2
    3
    4
    5
    6
    @RequestMapping("/selectForOne/{sId}")
    @Cacheable(value = "MYBATIS:com.chen.mysqlredisdemo.StudentMapper", key = "#sId",condition = "#sId>1800710301")
    public Student selectStudentForOne(@PathVariable int sId) {
    Student student = studentService.selectStudentForOne(sId);
    return student;
    }
    上面的例子就表示当查询的sId大于1800710318的时候才会执行缓存的操作

3、CachePut注解

  • 在支持Spring Cache的环境下,对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。
  • @CachePut也可以声明一个方法支持缓存功能。
  • 与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
  • @CachePut也可以标注在类上和方法上。使用@CachePut时我们可以指定的属性跟@Cacheable是一样的。

简而言之就是CachePut只会往缓存中写数据,不会从缓存中拿数据

4、CacheEvict注解

  • @CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。
  • @CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。
  • 其中value、key和condition的语义与@Cacheable对应的属性类似。即value表示清除操作是发生在哪些Cache上的(对应Cache的名称);key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key;condition表示清除操作发生的条件。
  • 与前面不同的不同的是有了两个多出来的属性:allEntriesbeforeInvocation

4.1、allEntries属性

  • allEntries是boolean类型,表示是否需要清除缓存中的所有元素。
  • 默认为false,表示不需要。当指定了allEntries为true时,Spring Cache将忽略指定的key。
  • 有的时候我们需要Cache一下清除所有的元素,这比一个一个清除元素更有效率。

4.2、beforeInvocation属性

  • 清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。
  • 使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。

5、Caching注解

@Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。
其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。

其例子如下

1
2
3
4
 @Caching(cacheable = @Cacheable("users"), evict = { @CacheEvict("cache2"), @CacheEvict(value = "cache3", allEntries = true) })
public User find(Integer id) {
returnnull;
}

上面的例子通过一个Caching注解,实现了三种注解同事的配置,相当于一个大集合

6、总结

SpringBoot中大量使用了注解、替代了原有的配置文件。
大大减少了冗余代码,方便地实现了注解中所设置好的功能。
使得我们的代码简洁易懂。
除了官方默认的注解,同时我们还可以自定义很多注解,极大方便了我们的使用。