Spring Caching缓存

简单的demo

  • 在想要加缓存的方法上加@Cacheable注解,在类上加@EnableCaching注解或者直接加载启动类上
package com.jsong.wiki.blog;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.stereotype.Component;

@EnableCaching
@Component
public class CacheService {

    @Cacheable("cache")
    public String getName(){
        System.out.println("cache");
        return "cache";
    }
}

当调用getName方法是,第一次调用没有缓存,会执行方法体,第二次调用的时候不会执行方法,直接在缓存中获取数据。


约束应用中可用的缓存

  • application.yml
    只要名字叫cache的缓存,
spring:
  cache:
    cache-names:
      - cache

当访问其他不存在的缓存时,会报错,启动的时候不会报错

java.lang.IllegalArgumentException: Cannot find cache named 'jsong' for Builder[public java.lang.String com.jsong.wiki.blog.CacheService.getName()] caches=[jsong] | key='' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='' | sync='false'

关闭缓存

关闭应用缓存
spring.cache.type=none

spring:
  cache:
    cache-names:
      - jsong
    type: none

几个重要的注解

@Cacheable

这个注解可以设置和获取缓存

public @interface Cacheable {
    @AliasFor("cacheNames")
    String[] value() default {};

    @AliasFor("value")
    String[] cacheNames() default {};

    String key() default "";

    String keyGenerator() default "";

    String cacheManager() default "";

    String cacheResolver() default "";

    String condition() default "";

    String unless() default "";

    boolean sync() default false;
}

支持主要参数

  • cacheNames,value:作用相同,都是指定缓存的名字,当同时定义cacheNames和value的时候,cacheNames的值要和value的值相同。
    demo
    @Cacheable(value = "cache1")
    public String getName(){
        return "cache1";
    }

    @Cacheable(value = "cache1")
    public String getName2(){
        return "cache2";
    }

单元测试
在访问getName()时,没有检测到有缓存,执行方法,把值放入到缓存cache1 并返回,getName2()和getName()标注的缓存value都是cache1,所以当执行getName2()时,发现缓存中有数据,并不执行方法,直接从缓存中取数据,所以,没有返回cache2,而是返回cahe1。

    @Test
    public void testCache(){
        System.out.println(cacheService.getName()); // cache1
        System.out.println(cacheService.getName2()); // cache1
    }

  • key:当前缓存的key,可以和value搭配使用,确定缓存。支持SpEL表达式(如:“#参数名”或者“#p参数index”)。
属性 描述 示例(#root可以省略)
methodName 当前方法名 #root.methodName
method 当前方法 #root.method.name
target 当前被调用的对象 #root.target
targetClass 当前被调用的对象的class #root.targetClass
args 当前方法参数组成的数组 #root.args[0]
caches 当前被调用的方法使用的Cache #root.caches[0].name

demo1

    @Cacheable(value = "cache1", key = "#root.method")
    public String getName() {
        return "cache1";
    }

    @Cacheable(value = "cache1", key = "#root.method")
    public String getName2() {
        return "cache2";
    }

单元测试
输出结果 cache1,cache2。因为两个缓存调用方法不是同一个方法,所以返回结果不同

    @Test
    public void testCache(){
        System.out.println(cacheService.getName()); // cache1
        System.out.println(cacheService.getName2()); // cache2
    }

demo2

    @Cacheable(value = "cache1", key = "#root.target")
    public String getName() {
        return "cache1";
    }

    @Cacheable(value = "cache1", key = "#root.target")
    public String getName2() {
        return "cache2";
    }

单元测试
输出结果返回cache1,cache1。因为两个方法调用的对象都是同一个对象。

    @Test
    public void testCache(){
        System.out.println(cacheService.getName()); // cache1
        System.out.println(cacheService.getName2()); // cache1
    }
  • condition :只有当条件满足时才会去检查缓存,支持SpEL表达式

demo

    @Cacheable(value = "cache1", key = "#root.target")
    public String getName() {
        return "cache1";
    }

    @Cacheable(value = "cache1", key = "#root.target", condition = "#p0>#p1")
    public String getName2(int i, int j) {
        return "cache2";
    }

单元测试
第一次调用getName2方法时,缓存中的数据位cache1,并且condition条件满足,所以输出缓存数据cache1。
第二次调用getName2方法时,condition条件不满足,所以执行方法,输出数据cache2。

    @Test
    public void testCache(){
        System.out.println(cacheService.getName()); // cache1
        System.out.println(cacheService.getName2(2,1)); // cache1
        System.out.println(cacheService.getName2(2,3)); // cache2
    }

@CachePut

这个注解主要是设置缓存,不能获取缓存
它的属性和@Cacheable差不多,这里就不再赘述了。

demo

    @Cacheable(value = "cache1", key = "#root.target")
    public String getName() {
        return "cache1";
    }

    @Cacheable(value = "cache1", key = "#root.target", condition = "#p0>#p1")
    public String getName2(int i, int j) {
        return "cache2";
    }

    @CachePut(value = "cache1", key = "#root.target", condition = "#p0>#p1")
    public String setCache1(int i, int j) {
        return "put-cache1";
    }

单元测试

    @Test
    public void testCache(){
//        System.out.println(cacheService.getName2(2,1));
//        System.out.println(cacheService.getName2(2,3));
        cacheService.setCache1(2,1);
        System.out.println(cacheService.getName()); // put-cache1
    }

@CacheEvict

清除缓存
当方法执行完成后,清除缓存,如果方法执行过程中报错,则不清除缓存。
新属性beforeInvocation当值为true时,在方法调用前就清除缓存,即使方法报错,也会清除缓存。
新属性allEntries当值为true时,清空所有缓存,忽略key。当值为false时,清空指定key的缓存,默认为false。

demo

    @Cacheable(value = "cache1", key = "#root.target")
    public String getName() {
        return "cache1";
    }

    @Cacheable(value = "cache1", key = "#p0", condition = "#p0>#p1")
    public String getName2(int i, int j) {
        return "cache2";
    }

    // cache1 指定key赋值
    @CachePut(value = "cache1", key = "#root.target", condition = "#p0>#p1")
    public String setCache1(int i, int j) {
        return "put-cache1";
    }

    // cache1 指定key赋值
    @CachePut(value = "cache1", key = "#p0", condition = "#p0>#p1")
    public String setCache2(int i, int j) {
        return "put-cache2";
    }

    // 清除cache1 指定key的缓存
    @CacheEvict(value = "cache1", key = "#root.target", condition = "#p0>#p1")
    public void evictCache(int i, int j) {
    }

    //  清除cache1的所有缓存,忽略key
    @CacheEvict(value = "cache1", allEntries = true, key = "#root.target", condition = "#p0>#p1")
    public void evictAllCache(int i, int j) {
    }

@Caching

可以同时定义多个注解属性
cacheable
put
evict

    @Caching(cacheable = @Cacheable(value = "cache1"), put = @CachePut(value = "cache2", key = "#root.target"), evict = @CacheEvict(value = "cache3", allEntries = true))
    public String caching() {
        return "caching";
    }

CacheManager

除了Spring自带的缓存,还可以用下面这些包管理缓存。

Generic
JCache (JSR-107) (EhCache 3, Hazelcast, Infinispan, and others)
EhCache 2.x
Hazelcast
Infinispan
Couchbase
Redis
Caffeine
Simple


发布了83 篇原创文章 · 获赞 21 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/JsongNeu/article/details/103602907