史上最全的Spring Boot缓存@Cacheable,@CachePut,@CacheEvict,@Caching,@CacheConfig注解详细解析,看这一篇就够了


前言

Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口来统一不同的缓存技术,并支持使用JCache(JSR-107)注解简化我们开发。


一、两个核心接口

CacheManager:
       定义了创建、配置、获取、管理和控制多个唯一命名的Cache,这些Cache存在于CacheManager的上下文中。一个CacheManager仅被一个CachingProvider所拥有。
Cache:
       是一个类似Map的数据结构并临时存储以Key为索引的值。一个Cache仅被一个CacheManager所拥有。此外Cache接口下Spring还提供了各种xxxCache的实现;如RedisCache,EhCacheCache , ConcurrentMapCache等。

二、快速体验缓存步骤

1、添加依赖文件

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

2、开启基于注解的缓存

@EnableCaching
public class SpringbootApplication {
	public static void main(String[] args) {
		SpringApplication.run(SpringbootApplication.class, args);
	}
}

3、标注缓存注解即可

package com.test.cache.service;

import com.test.cache.bean.Employee;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;

@CacheConfig(cacheNames = "emp")
@Service
public class EmployeeService {
    @Cacheable(value = {"emp"},key = "#id")
    public Employee getEmployee(String id) {
        System.out.println("getEmployee:" + id);
        return null;
    }

    @CachePut(key = "#result.id")
    public Employee updateEmployee(Employee employee) {
        System.out.println("updateEmployee:" + employee);
        return null;
    }

    @CacheEvict(value = "emp", beforeInvocation = true)
    public void deleteEmployee(String id) {
        System.out.println("deleteEmployee:" + id);
    }

    @Caching(cacheable = {@Cacheable(key = "#lastName")}, put = {@CachePut(key = "#result.id"), @CachePut(key = "#result.email")})
    public Employee getEmpByLastName(String lastName) {
        System.out.println("getEmpByLastName:" + lastName);
        return null;
    }
}

提示:每次调用需要缓存功能的方法时,Spring会检查指定参数的指定的目标方法是否已经被调用过;如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。


上述代码中@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig注解都有什么作用以及每个注解的属性都代表什么意思该如何使用呢?别急,我们下面开始进行缓存相关注解的详细解释……

三、缓存相关注解详解

1、@Cacheable

       ㈠、作用

              方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,如果没有就运行方法并将结果放入缓存;以后再来调用就可以直接使用缓存中的数据;

       ㈡、属性

              ①.cacheNames/value:指定缓存组件的名字,将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存。
              ②.key:缓存数据使用的key可以用它来指定,默认是使用方法参数的值。可以使用SpEL表达式:

如 key = “#id” 等同于 key = “#a0” 或 key = “#p0” 或 key = "#root.args[0]"表示取出参数id的值,详细可以有哪些写法呢?如下图:

在这里插入图片描述提示:@Cacheable的key是不能用#result,因为@Cacheable会先根据key去缓存中查询,如果没有就创建缓存。如果使用#result则表示结果值还没有就拿结果值做缓存很明显不合理
              ③.keyGenerator:key的生成器,可以自己指定key的生成器的组件id。key/keyGenerator:二选一使用;

如果想自定义key的生成策略该怎么做呢?比如让key的生成方式如:getEmployee[x]

@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()+"]";
            }
        };
    }
    /**
     * 注意此方法应该放在service中喔,只是我偷懒所以放在了这里,
     * 注意看keyGenerator属性是Bean的名称
     */
    @Cacheable(value = {"emp"},keyGenerator = "myKeyGenerator")
    public Employee getEmployee(String id) {
        System.out.println("getEmployee:" + id);
        return null;
    }
}

              ④.cacheManager:指定缓存管理器,或者cacheResolver指定获取解析器
              ⑤.condition:指定符合条件的情况下才缓存;

如:condition = “#id>0”:第一个参数的值大于0的时候才进行缓存;condition = “#a0>1”:第一个参数的值大于1的时候才进行缓存

              ⑥.unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;unless也可以获取到结果进行判断。

如:unless = “#result == null”:如果方法返回结果值是null,结果不缓存;unless = “#a0==2”:如果第一个参数的值是2,结果不缓存;

              ⑦.sync:是否使用异步模式
提示:sync异步模式下不支持unless 属性,sync与unless两者用其一

       ㈢、运行流程

              ①.方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取;(CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建。
              ②.去Cache中查找缓存的内容,使用一个key,默认就是方法的参数;key是按照某种策略生成的;默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成key;
              SimpleKeyGenerator生成key的默认策略;
                            如果没有参数:key=new SimpleKey()
                            如果有一个参数:key=参数的值
                            如果有多个参数:key=new SimpleKey(params)
              ③.没有查到缓存就调用目标方法;
              ④.将目标方法返回的结果,放进缓存中;

2、@CachePut

       ㈠、作用

              先调用方法,修改了数据库的数据后,同时更新缓存;

       ㈡、属性

              参考本章@Cacheable属性
提示:使用@CachePut(value = "emp",key = "#result.id")注解更新数据时,记得value一定要与@Cacheable的缓存名称和key值一致,不然获取值时不是更新后的值

3、@CacheEvict

       ㈠、作用

              缓存清除

       ㈡、属性

              ①.key:指定要清除的数据。
              ②.allEntries:默认为false,为true时清除这个缓存中所有的数据。
              ③.beforeInvocation:默认为false,为false时代表缓存清除操作是在方法执行之后执行,如果出现异常缓存就不会清除。为true时代表清除缓存操作是在方法运行之前执行,无论方法是否出现异常,缓存都清除。

4、@Caching

       ㈠、作用

              定义复杂的缓存规则,就是@Cacheable、@CachePut、@CacheEvict的组合注解,其中三个属性都是数组形式。

       ㈡、属性

              ①.@Cacheable:参考本章@Cacheable解释
              ②.@CachePut:参考本章@CachePut解释
              ③.@CacheEvict:参考本章@CacheEvict解释

5、@CacheConfig

       ㈠、作用

              抽取缓存的公共配置,标记类时此类所有带有缓存注解的方法都无需再配置属性。

       ㈡、属性

              ①.cacheNames:指定缓存组件的名字,将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存。
              ②.keyGenerator:key的生成器,可以自己指定key的生成器的组件id。
              ③.cacheManager:指定缓存管理器,或者cacheResolver指定获取解析器。

总结

@Cacheable核心
       1)、springboot缓存默认使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件将数据保存在 ConcurrentMap<Object, Object>中
       2)、key使用keyGenerator生成的,默认是SimpleKeyGenerator

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring框架通过Spring Cache提供了一套强大的缓存体系,可以轻松地实现缓存数据,提高应用程序的性能。Spring框架提供了三个主要的注解来实现缓存:@Cacheable、@CachePut和@CacheEvict。 @Cacheable注解用于将方法的结果缓存起来,以便在下次请求时,如果参数相同,则可以直接从缓存中获取结果,而不需要重新计算。该注解适用于如果计算结果比较耗时,或者需要从数据库或其他外部资源中提取数据的情况。 @CachePut注解用于更新缓存中的数据。它与@Cacheable注解类似,但不同的是,它总是更新缓存数据,而不管缓存中是否已经存在该key的值。所以,可以使用这个注解来更新缓存中的数据。 @CacheEvict注解用于从缓存中删除数据。它在需要删除缓存数据的情况下使用。它可以删除指定的key对应的缓存,也可以清空所有缓存数据。 这三个注解都有一个可选参数Named:如果指定了该参数,则缓存将使用指定的名称使用。如果未指定,则使用默认的名称。可以使用不同名称的缓存来存储不同类型的数据,并使用不同的缓存策略来控制它们的存储方式。 除了Spring自带的缓存提供者之外,还可以使用其他的缓存提供者,如Ehcache、Redis、Memcached等等。在使用缓存时,需要注意的是,不同的缓存提供者之间可能会有不同的限制和性能差异。因此,必须根据实际情况选择最适合的缓存提供者和缓存策略,以获取最好的性能和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值