Spring缓存注解@Cacheable

文章目录

  • Spring缓存注解@Cacheable
    • 一、简介
    • 二、@Cacheable能干什么?
    • 三、@Cacheable 注解使用详细介绍
    • 四、常用属性说明
    • 五、Spring实现本地缓存(本人亲测!!!)


Spring缓存注解@Cacheable

一、简介

Spring 从 3.1 开始就引入了对 Cache (缓存)的支持。定义了 org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 接口来统一不同的缓存技术。并支持使用 JCache(JSR-107)注解简化我们的开发。
其使用方法和原理都类似于 Spring 对事务管理的支持。Spring Cache 是作用在方法上的,其核心思想是,当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值对存在缓存中
注意:

  1. 每次调用需要缓存功能的方法时,Spring 会检查指定参数的指定目标方法是否已经被调用过,如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。
  2. 此缓存保存在内存中,如果关闭或重启服务,缓存将被清除。如果要长久保存,可以结合Redis

二、@Cacheable能干什么?

目前我遇到一个关于接口查询里面包含非常多的计算导致查询非常慢的情况
而我们希望的是,第一次调用这个方法时,返回的数据能被放到服务器端(本地缓存)的缓存里,以便于后面要调用这个方法时,能直接从缓存里取到,这样就不用再查数据库占用资源了。而@Cacheable的作用就是这个。

三、@Cacheable 注解使用详细介绍

  1. 导入本地缓存的jar
	
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-cacheartifactId>
		dependency>
		<dependency>
			<groupId>com.github.ben-manes.caffeinegroupId>
			<artifactId>caffeineartifactId>
		dependency>
  1. 开启基于注解的缓存,使用 @EnableCaching 标注在 springboot 主启动类上
  2. 标注缓存注解
    Spring缓存注解@Cacheable_第1张图片

四、常用属性说明

  • cacheNames/value :用来指定缓存组件的名字,将方法的返回结果放在哪个缓存中,可以是数组的方式,支持指定多个缓存。(就是个自己取的名字,通过它指明了第一次调用这个方法时返回的List数据将被存在内存的哪里)

例如: mycache就是缓存的名称

@Cacheable(value=”mycache”)
@Cacheable(value={”cache1”,”cache2”}
  • key :缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。(这个 key 你可以使用 SpEL表达式来编写)

SpEL:(spring expression language) 是一种表达式语言,是一种强大,简洁的装配Bean的方式。
他可以通过运行期间执行的表达式将值装配到我们的属性或构造函数当中,也可以调用JDK中提供的静态常量,获取外部Properties文件中的的配置。
基本语法 :SpEL 使用 #{…} 作为定界符,所有在大括号中的字符都被认为是 SpEL 表达式。

总结一下使用 spEL 去编写 key 可以用的一些元数据:
Spring缓存注解@Cacheable_第2张图片

  • keyGenerator :key 的生成器。 key 和 keyGenerator 二选一使用
  1. key
    缓存数据时使用的 key。默认使用的是方法参数的值。
@Cacheable(value = "mycache",key = "#username")
public List<Message> getMessage(String username, int language) {
     return List;
}

这里与参数username对应,当传入的username值变了的话就不去取缓存里的数据了,而是执行getMessage方法。(这是必须的,因为username变了,返回值也就变了,缓存里的数据不符合了,因此这个选项很重要)。spring默认用方法的签名来当做key。

  1. keyGenerator
    key 的生成器,可以自己指定 key 的生成器,通过这个生成器来生成 key。
 @Bean(name = "orgKeyGenerator")
    public KeyGenerator keyGenerator(){
     return new KeyGenerator() {

         /**
          * Generate a key for the given method and its parameters.
          *
          * @param target the target instance
          * @param method the method being called
          * @param params the method parameters (with any var-args expanded)
          * @return a generated key
          */
         @Override
         public Object generate(Object target, Method method, Object... params) {
             return method.getName() + "[" + Arrays.asList(params).toString() + "]";
         }
     };
    }

orgKeyGenerator就是自定义key的值,这样就可以把前端传入的对象给传入进来,根据前端的参数与方法名称来确定独一无二的key

       @Override
    @Cacheable(value = "QaOrganizationMatrixDaily", keyGenerator = "orgKeyGenerator")
    public Map<String, Object> getDailyData(MatrixDailyDTO matrixDailyDTO) {

        long s = System.currentTimeMil

condition :可以用来指定符合条件的情况下才缓存

@Cacheable(value = "mycache",key = "#username", condition = "#language = 1")
public List<Message> getMessage(String username, int language) {
     return List;
}

这个例子中,只有传入的语言代码是1,返回的List才会被缓存起来,如果给language传了别的值,那List是不会缓存起来的。

unless :否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然你也可以获取到结果进行判断。(通过 #result 获取方法结果)

@Cacheable(value = "mycache",key = "#username", condition = "#language = 1", unless = "#result==null" )
public List<Message> getMessage(String username, int language) {
     return result.success();
}

这个例子中,当返回值为空时,不进行缓存
sync :是否使用异步模式。默认是方法执行完,以同步的方式将方法返回的结果存在缓存中。

五、Spring实现本地缓存(本人亲测!!!)

Spring缓存注解@Cacheable_第3张图片


import com.google.common.cache.CacheBuilder;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.guava.GuavaCache;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

@Configuration
@EnableCaching
public class CacheConfig {
    @Bean
    public CacheManager localCacheManager() {
        SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
        //把各个cache注册到cacheManager中,GuavaCache实现了org.springframework.cache.Cache接口
        simpleCacheManager.setCaches(Arrays.asList(
                //CacheBuilder构建多个cache
                new GuavaCache(
                        "QaOrganizationMatrixDaily",//定义cache名称:@Cacheable的cacheNames(等价value)属性要和此对应
                        CacheBuilder
                                .newBuilder()
                                .expireAfterWrite(1, TimeUnit.HOURS)//参数:过期时长、单位
                                .build()
                )

        ));
        return simpleCacheManager;
    }

    @Bean(name = "orgKeyGenerator")
    public KeyGenerator keyGenerator(){
     return new KeyGenerator() {

         /**
          * Generate a key for the given method and its parameters.
          *
          * @param target the target instance
          * @param method the method being called
          * @param params the method parameters (with any var-args expanded)
          * @return a generated key
          */
         @Override
         public Object generate(Object target, Method method, Object... params) {
             return method.getName() + "[" + Arrays.asList(params).toString() + "]";
         }
     };
    }
}

    @Override
    @Cacheable(value = "QaOrganizationMatrixDaily", keyGenerator = "orgKeyGenerator")
    public Map<String, Object> getDailyData(MatrixDailyDTO matrixDailyDTO) {

你可能感兴趣的:(spring,spring,java,缓存)