Spring Cache基本使用

Spring 从 3.1 版本开始定义缓存抽象来统一不同的缓存技术;在应用层面与后端存储之间,提供了一层抽象,这层抽象目的在于封装各种可插拔的后端存储( ehcache, redis, guava),最小化因为缓存给现有业务代码带来的侵入。

一、Spring Cache简介

Spring Cache 是 Spring 框架提供的一个缓存抽象,实现了基于注解的缓存功能,它能够轻松地集成到 Spring 应用程序中,为方法调用的结果提供缓存支持,从而提高应用程序的性能和响应速度。

Spring Cache 提供了一种声明式的缓存机制,可以在方法上使用注解来指定需要进行缓存的方法,而无需编写繁琐的缓存代码。

Spring Cache 基本介绍:

  • 声明式缓存支持:Spring Cache 提供了一种声明式的缓存机制,通过在方法上使用注解来声明需要进行缓存的方法。比如:@Cacheable、@CachePut、@CacheEvict等注解。
  • 灵活的缓存策略:Spring Cache 提供了多种灵活的缓存策略,可以根据具体需求选择合适的缓存方案。比如:基于内存缓存、基于 Redis、Ehcache 等第三方缓存框架的集成。
  • 支持缓存管理器:Spring Cache 支持多种缓存管理器,可以根据需要选择适合的缓存管理器。比如:ConcurrentMapCacheManager、EhCacheCacheManager、RedisCacheManager 等。
  • 适用于各种应用场景:Spring Cache 适用于各种应用场景,可以用于缓存方法的返回值、类级别的缓存、缓存的条件判断等。

Spring Cache核心抽象主要体现在两个接口上:

  • org.springframework.cache.cache接口:cache代表缓存组件规范定义(缓存本身),包含缓存的各种操作集合。比如:增加、删除、读取等。
  • org.springframework.cache.cachemanager接口:CacheManager 是 Spring 各种缓存的抽象接口。抽象的意义在于屏蔽实现细节的差异和提供扩展性,这一层cache的抽象解耦了缓存的使用和缓存的后端存储,这样后续可以方便的更换后端存储。

Spring提供了 Cache接口下各种 XxxCache实现。比如:RedisCache, EhCacheCache, ConcurrentMapCache, JCacheCache等。

Spring支持的常用 CacheManager 如下:

Spring Cache 默认使用 ConcurrentMapCacheManager 作为缓存管理器。

在这里插入图片描述
通过使用 Spring Cache,可以轻松地为应用程序中的方法调用提供缓存支持,从而提高应用程序的性能和响应速度,减少对数据库或其他资源的频繁访问。

每次调用需要缓存功能的方法时,Spring 会检查检查指定参数的指定的目标方法是否已经被调用过。

  • 如果有就直接从缓存中获取方法调用后的结果。
  • 如果没有就调用方法并缓 存结果后返回给用户。下次调用直接从缓存中获取。

二、Spring Cache使用

Spring Cache依赖如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

在spring boot项目中,无需添加 Spring Cache 的依赖,因为 Spring Boot 已经自动集成了 Spring Cache。

1、接入Redis使用Spring Cache

添加 Redis依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

项目配置文件(application.yml)中添加 Redis配置信息:

spring:
  ## Redis 配置信息
  redis:
    host: 127.0.0.1
    port: 6379
    password: xxxxxx
    database: 1

1.1 Redis配置类

Redis默认使用 JdkSerializationRedisSerializer序列化器。

  • RedisTemplate 中,k和v默认的序列化方案是 JdkSerializationRedisSerializer 。
  • RedisTemplate<String, Object> 中,k和v默认的序列化方案是 JdkSerializationRedisSerializer 。
  • StringRedisTemplate 中,k和v默认的序列化方案是 StringRedisSerializer 。默认情况下,前面不会有前缀。
@Configuration
public class RedisConfiguration {

    @Primary
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setHashKeySerializer(RedisSerializer.string());

        redisTemplate.setValueSerializer(RedisSerializer.java());
        redisTemplate.setHashValueSerializer(RedisSerializer.java());
        redisTemplate.setConnectionFactory(factory);
        // 调用 afterPropertiesSet()方法执行初始化操作
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

1.2 Spring Cache配置类

@EnableCaching注解:开启缓存功能,一般放在启动类或者配置类上。

CacheManager可以不用注入,Spring框架会自动注入的。如果我们手动注入,会使用我们自己注入的(适合自定义相关配置信息)。

下面使用 RedisCacheManager作为缓存缓存管理。

@EnableCaching
@Configuration
public class CacheConfiguration {

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheManager cacheManager = RedisCacheManager.create(connectionFactory);
        return cacheManager;
    }
}

2、核心注解使用

Spring Cache提供了下面几个核心注解完成缓存功能的实现。

  • @EnableCaching:开启缓存功能
  • @Cacheable:定义缓存,用于触发缓存
  • @CachePut:定义更新缓存,触发缓存更新
  • @CacheEvict:定义清除缓存,触发缓存清除
  • @Caching:组合定义多种缓存功能
  • @CacheConfig:定义公共设置,位于class之上

2.1 @Cacheable注解

@Cacheable注解:定义缓存数据或者获取缓存数据操作。
@Cacheable 注解可以应用于类或方法上。当应用于类上时,表示该类的所有方法的返回值都可以被缓存;当应用于方法上时,表示特定方法的返回值可以被缓存。

该注解标注的方法每次被调用前都会触发缓存校验,校验指定参数的缓存是否已存在(已发生过相同参数的调用),若存在,直接返回缓存结果,否则执行方法内容,最后将方法执行结果保存到缓存中。

2.1.1 主要属性

主要属性如下:

  • value:必填,指定缓存数据存放在哪块命名空间(缓存名)。用于指定要操作的缓存名称或缓存管理器的名称。可以是一个字符串,也可以是一个字符串数组,用于指定多个缓存名称。
  • cacheNames:与 value 差不多,二选一即可。
  • key:可选,指定缓存条目的键,用于唯一标识缓存中的条目。SpEL 表达式可以用于动态地生成键值。如果不指定 key,Spring Cache 将会使用默认的键生成策略来生成键值。
  • condition:条件符合则缓存。指定一个 SpEL 表达式,用于判断是否执行缓存操作。只有当表达式的值为 true 时,才会执行缓存操作。默认为空,表示始终执行缓存操作。
  • unless:条件符合则不缓存。指定一个 SpEL 表达式,用于判断是否不执行缓存操作。只有当表达式的值为 false 时,才会执行缓存操作。默认为空,表示始终执行缓存操作。
  • keyGenerator:指定一个自定义的键生成器,用于生成缓存条目的键值。默认为空,表示使用默认的键生成策略。key/keyGenerator二选一使用。
  • cacheManager:指定一个自定义的缓存管理器,用于指定缓存的实现。默认为空,表示使用默认的缓存管理器。
  • cacheResolver:指定一个自定义的缓存解析器,用于解析缓存的实现。默认为空,表示使用默认的缓存解析器。
  • sync:指定是否启用同步模式。如果设置为 true,那么缓存操作将在调用方法的同一线程中执行,否则将在后台线程中异步执行。默认为 false。
2.1.2 使用
    @Cacheable(value = "userCache_", key = "#id", unless = "#result==null")
    @Override
    public UserDTO getById(Long id) {
        if (id == null || id <= 0L) {
            return null;
        }
        UserDO userDO = userMapper.selectById(id);
        return do2DTO(userDO);
    }

unless参数里的 #result为方法的返回值。所以,判断方法返回值为 null 时,则不缓存。

在这里插入图片描述

2.2 @CachePut注解

@CachePut注解:更新缓存数据操作。
@CachePut与 @Cacheable 不同,@CachePut 不会检查缓存中是否已经存在相同键的条目,而是直接将方法的返回值更新到缓存中。

该注解用于更新缓存,无论结果是否已经缓存,都会在方法执行结束插入缓存,相当于更新缓存。一般用于更新方法之上。

2.2.1 主要属性

主要属性如下:

  • value:必填,指定缓存数据存放在哪块命名空间(缓存名)。用于指定要操作的缓存名称或缓存管理器的名称。可以是一个字符串,也可以是一个字符串数组,用于指定多个缓存名称。
  • cacheNames:与 value 差不多,二选一即可。
  • key:可选,指定缓存条目的键,用于唯一标识缓存中的条目。SpEL 表达式可以用于动态地生成键值。如果不指定 key,Spring Cache 将会使用默认的键生成策略来生成键值。
  • condition:条件符合则缓存。指定一个 SpEL 表达式,用于判断是否执行缓存操作。只有当表达式的值为 true 时,才会执行缓存操作。默认为空,表示始终执行缓存操作。
  • unless:条件符合则不缓存。指定一个 SpEL 表达式,用于判断是否不执行缓存操作。只有当表达式的值为 false 时,才会执行缓存操作。默认为空,表示始终执行缓存操作。
  • keyGenerator:指定一个自定义的键生成器,用于生成缓存条目的键值。默认为空,表示使用默认的键生成策略。key/keyGenerator二选一使用
  • cacheManager:指定一个自定义的缓存管理器,用于指定缓存的实现。默认为空,表示使用默认的缓存管理器。
  • cacheResolver:指定一个自定义的缓存解析器,用于解析缓存的实现。默认为空,表示使用默认的缓存解析器。
2.2.2 使用
    @CachePut(cacheNames = "userCache_", key = "#updateRequest.userId", unless = "#result == null")
    @Override
    public UserDTO update2(UserUpdateRequest updateRequest) {
        Long id = updateRequest.getUserId();
        if (id == null || id <= 0) {
            return null;
        }
        // 修改用户信息
        UserDO updateDO = new UserDO();
        BeanUtils.copyProperties(updateRequest, updateDO);
        updateDO.setUpdateTime(LocalDateTime.now());
        userMapper.updateById(updateDO);
        
        // 演示效果
        UserDO userDO = userMapper.selectById(id);
        return do2DTO(userDO);
    }

注意:这里设置的 key一定要和执行缓存保存的方法设置 key一致,否则无法准确更新。

使用方法参数作为 key的示例:

   @Cacheable(value="users", key="#id")
   public User find(Integer id) {
      return null;
   }
   @Cacheable(value="users", key="#p0")
   public User find(Integer id) {
      return null;
   }
   // 推荐使用
   @Cacheable(value="users", key="#user.id")
   public User find(User user) {
      return null;
   }
   @Cacheable(value="users", key="#p0.id")
   public User find(User user) {
      return null;
   }

除了上述使用方法参数作为 key之外,Spring还为我们提供了一个 root对象可以用来生成 key。通过该 root对象我们可以获取到以下信息。

在这里插入图片描述

2.3 @CacheEvict注解

@CacheEvict注解:删除缓存数据操作。

2.3.1 主要属性

主要属性如下:

  • value:必填,指定缓存数据存放在哪块命名空间(缓存名)。用于指定要操作的缓存名称或缓存管理器的名称。可以是一个字符串,也可以是一个字符串数组,用于指定多个缓存名称。
  • cacheNames:与 value 差不多,二选一即可。
  • key:可选,指定缓存条目的键,用于唯一标识缓存中的条目。SpEL 表达式可以用于动态地生成键值。如果不指定 key,Spring Cache 将会使用默认的键生成策略来生成键值。
  • condition:条件符合则缓存。指定一个 SpEL 表达式,用于判断是否执行缓存操作。只有当表达式的值为 true 时,才会执行缓存操作。默认为空,表示始终执行缓存操作。
  • eyGenerator:指定一个自定义的键生成器,用于生成缓存条目的键值。默认为空,表示使用默认的键生成策略。key/keyGenerator二选一使用。
  • cacheManager:指定一个自定义的缓存管理器,用于指定缓存的实现。默认为空,表示使用默认的缓存管理器。
  • cacheResolver:指定一个自定义的缓存解析器,用于解析缓存的实现。默认为空,表示使用默认的缓存解析器。
  • allEntries:是否清空所有缓存,默认为 false。如果指定为 true,则方法调用后将立即清空所有的缓存。
  • beforeInvocation:是否在方法执行前就清空,默认为 false。如果指定为 true,则在方法执行前就会清空缓存。
2.3.2 使用
    @CacheEvict(value = "userCache_", key = "#id", condition = "#result.success == true")
    //@CacheEvict(value = "userCache_", allEntries = true)
    @Override
    public BaseOperateResult deleteById(Long id) {
        BaseOperateResult operateResult = new BaseOperateResult();

        if (id == null || id <= 0L) {
            operateResult.setSuccess(false);
            operateResult.setErrorCode(DemoErrorCodeEnum.ID_IS_NOT_NULL.errorCode());
            return operateResult;
        }
        UserDTO oldDTO = getById(id);
        if (oldDTO == null) {
            operateResult.setSuccess(Boolean.FALSE);
            operateResult.setErrorCode(DemoErrorCodeEnum.RECORD_NOT_FOUND.errorCode());
            return operateResult;
        }
        // 不允许删除管理员账号
        if ("admin".equals(oldDTO.getUsername())) {
            operateResult.setSuccess(Boolean.FALSE);
            operateResult.setErrorCode(DemoErrorCodeEnum.NOT_DELETE_ADMIN_USER.errorCode());
            return operateResult;
        }

        // 用户逻辑删除
        UserDO updateDO = new UserDO();
        updateDO.setUserId(id);
        updateDO.setDelFlag(CommonConstants.DELETE_FLAG_DELETED);
        userMapper.updateById(updateDO);

        operateResult.setId(id);
        operateResult.setSuccess(true);
        return operateResult;
    }

注意:

  • 这里设置的 key一定要和执行缓存保存的方法设置 key一致,否则无法准确删除。
  • condition参数里的 #result为方法的返回值。所以,判断方法返回值的 success = true 时,则执行删除缓存操作。
  • 如果配置了 allEntries属性,则会删除 value为命名空间下的所有缓存条目的键,此时配不配 key属性都不会影响 allEntries属性操作。

3、全局配置Cache参数信息(了解)

参考文章:spring-boot+redis实现缓存功能:https://www.jianshu.com/p/be2c09cd27d8

项目配置文件(application.yml)中可以添加 cache配置信息。

注意:

  • 如果使用 Spring框架自动注入 CacheManager的方式,下面配置会生效。
  • 如果使用我们手动注入的自定义了 CacheManager方式,下面配置不会生效,而是使用我们自定义的相关配置。
spring:
  ## Redis 配置信息
  redis:
    host: 127.0.0.1
    port: 6379
    password: xxxxxx
    database: 1
  ## Spring cache配置信息
  cache:
    # 缓存的类型,redis
    type: redis
    redis:
      # 缓存数据key是否使用前缀,默认是true
      use-key-prefix: true
      #缓存数据key的前缀,在上面的配置为true时有效,
      key-prefix: 'demo:'
      # redis中缓存超时的时间,默认60000ms
      time-to-live: 120000

参考文章:

– 求知若饥,虚心若愚。

  • 28
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring CacheSpring框架提供的一个缓存抽象层,可以方便地在应用中添加缓存功能。下面是Spring Cache基本使用方法: 1. 添加依赖:在项目的pom.xml文件中添加Spring Cache的依赖项。 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> ``` 2. 配置缓存管理器:在配置类中添加@EnableCaching注解,并配置缓存管理器。 ```java @Configuration @EnableCaching public class CacheConfig { @Bean public CacheManager cacheManager() { SimpleCacheManager cacheManager = new SimpleCacheManager(); cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("cacheName"))); return cacheManager; } } ``` 3. 在需要缓存的方法上添加缓存注解:使用@Cacheable注解来标记需要进行缓存的方法。 ```java @Service public class MyService { @Cacheable("cacheName") public String getData(String key) { // 这里是从数据库或其他外部资源获取数据的逻辑 return data; } } ``` 4. 测试缓存功能:在测试类中调用被缓存的方法,多次调用可以看到第一次调用时会执行方法体,后续调用则从缓存中获取结果。 ```java @SpringBootTest class CacheTest { @Autowired private MyService myService; @Test public void testCache() { String result1 = myService.getData("key"); String result2 = myService.getData("key"); // result1和result2的值应该相同,第二次调用从缓存中获取结果 } } ``` 以上是Spring Cache基本使用方法,通过配置缓存管理器和使用@Cacheable注解,可以轻松地在Spring应用中添加缓存功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值