SpringBoot使用Spring缓存注解

声明:Spring缓存注解的使用非常简单,主要是理解,所以本文主要以示例+注释(图片版)进行说明,核心部分
           会给出文字版;当然本人测试时完整的项目代码会放在GitHub上,链接见本文末。


目录

启用Spring缓存注解技术

Spring缓存注解总体介绍

缓存注解的常用属性(以示例进行说明)

key

condition

cacheNames

unless

allEntries

beforeInvocation

缓存注解使用在返回值为viod方法上的测试


背景简述: 
       自Spring3.1开始,Spring就自带了对缓存的支持。我们可以直接使用Spring缓存技术将某些数据放入本机的缓存中;Spring缓存技术也可以搭配其他缓存中间件(如Redis等)进行使用,将某些数据写入到缓存中间件(缓存中间件可能在其他机器上)中。


启用Spring缓存注解技术

第一步:确认Spring版本不低于3.1。

注:本人用的是SpringBoot2.1.2.RELEASE,对应的Spring版本为5.1.4.RELEASE。

第二步:在SpringBoot启动类上启用Spring缓存技术。

第三步:在类上或类中的方法上使用缓存注解。

注:这个【类】指的是注入了Spring容器中的。如果没有注入,那么在该类上或该类中的缓存注解是不会生效的


Spring缓存注解总体介绍

Spring提供的缓存注解有:

常用的注解有:@EnableCaching、@Cacheable、@CacheEvict、@CachePut、@Caching、@CacheConfig。

提示:本部分提到的key,可见本文下面关于缓存注解各属性的介绍。

@EnableCaching:开关性注解,在项目启动类或某个配置类上使用此注解后,则表示允许使用注解的方式进行缓存操作,如:

@Cacheable可用于类或方法上;在目标方法执行前,会根据key先去缓存中查询看是否有数据,有就直接
                         返回缓存中的key对应的value值。不再执行目标方法;无则执行目标方法,并将方法的返回值
                         作为value,并以键值对的形式存入缓存,
如:

@CachePut可用于类或方法上;在执行完目标方法后,并将方法的返回值作为value,并以键值对的形式存入缓存中,如:

@CacheEvict可用于类或方法上;在执行完目标方法后,清除缓存中对应key的数据(如果缓存
                          中有对应key的数据缓存的话)
,如:

@Caching此注解即可作为@Cacheable、@CacheEvict、@CachePut三种注解中的的任何一种或几种来使用,如:

@CacheConfig@Cacheable、@CacheEvict、@CachePut这三个注解的cacheNames属性是必
                             填项(或value属性是必填项,因为value属性是cacheNames的别名属性);如果上述
                             三种注解都用的是同一个cacheNames的话,那么在每此都写cacheNames的话,
                             就会显得麻烦。如将@CacheConfig注解就是来配置一些公共属性(如:cacheNames、
                             keyGenerator等)的值的,如:


缓存注解的常用属性(以示例进行说明)

key

        key的来源可分为三类,分别是:默认的、keyGenerator生成的、主动指定的。

下面在具体代码中进行说明,注意阅读注释说明!

默认key

keyGenerator生成key

编写配置类、定制化key生成器:

import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;

/**
 * 定制化CachingConfigurer
 *
 * @author JustryDeng
 * @date 2019/4/11 16:26
 */
@Configuration
public class MyCachingConfigurer extends CachingConfigurerSupport {

    /**
     * 定制化key生成器
     *
     * 设置  全限定类名 + 方法名 + 参数名 共同组成 key
     *
     * @return key生成器
     * @date 2019/4/12 14:09
     */
    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return (Object target, Method method, Object... params) -> {
            StringBuilder sb = new StringBuilder(16);
            sb.append(target.getClass().getName());
            sb.append("_");
            sb.append(method.getName());
            sb.append("_");
            for (int i = 0; i < params.length; i++) {
                sb.append(params[i]);
                if (i < params.length - 1) {
                    sb.append(",");
                }
            }
            return sb.toString();
        };
    }
}

此时,若使用缓存注解时不指定key属性,那么就会默认采用Key生成器生成的注解:

主动指定key

condition

       在激活注解功能前,进行condition验证,如果condition结果为true,则表明验证通过,缓存注解生效;否则缓存注解不生效

condition作用时机在缓存注解检查缓存中是否有对应的key-value 之前。
                                     注:缓存注解检查缓存中是否有对应的key-value 在 运行目标方法之前,
                                            所以 condition作用时机也在运行目标方法之前。

实验示例

验证:

cacheNames

         通过cacheNames对数据进行隔离,不同cacheName下可以有相同的key。也可称呼cacheName为命名空间。实际上(以spring-cache为例),可以通过设置RedisCacheConfiguration#usePrefix的true或false来控制是否使用前缀。如果否,那么最终的redis键就是key值;如果是,那么就会根据cacheName生成一个前缀,然后再追加上key作为最终的redis键.cacheName还有其它重要的功能:cacheName(就像其名称【命名空间】所说)实现了数据分区的功能,一些操作可以直接按照命名空间批量进行。如:spring框架中的Cache实际对应的就是一个【命名空间】,spring会先去找到数据所在的命名空间(即:先找到对应的Cache),再由Cache结合key,最终定位到数据

下面验证的是当同时指定多个cacheName时,从哪一个cacheName取数据。

这里先给出结论

若属性cacheNames(或属性value)指定了多个命名空间;

  1. 当进行缓存存储时,会在这些命名空间下都存一份key-value。

  2. 当进行缓存读取时,会按照cacheNames值里命名空间的顺序,挨个挨个从命名空间中查找对应的key,如果在某个命名空间中查找打了对应的缓存,就不会再查找排在后面的命名空间,也不会再执行对应方法,直接返回缓存中的value值

实验示例

验证:

unless

       功能是:是否令注解(在方法执行后的功能)不生效;若unless的结果为true,则(方法执行后的功能)不生效;若unless的结果为false,则(方法执行后的)功能生效

注:unless默认为"",即相当于默认为false。

unless的作用时机目标方法运行后。
                                 注:如果(因为直接从缓存中获取到了数据,而导致)目标方法没有被执行,那么unless字段不生效

举例说明一
        对于@Cacheable注解,在执行目标方法前,如果从缓存中查询到了数据,那么直接返回缓存中的数据;如果从 缓存中没有查询到数据,那么执行目标方法,目标方法执行完毕之后,判断unless的结果,若unless的结果为true,那么不缓存方法的返回值;若unless的结果为false,那么缓存方法的返回值。

举例说明二
        对于@CachePut注解,在目标方法执行完毕之后,判断unless的结果,若unless的结果为true,那么不缓存方法的返回值;若unless的结果为false,那么缓存方法的返回值。

注:因为unless的作用时机是在方法运行完毕后,所以我们可以用SpEL表达式#result 来获取方法的返回值

实验示例

验证:

说明:本人跑了几次此测试方法,每次随机产生的key(从代码里面可知,本人已入参参数为key)都是之前缓存
           里面没有的,也就是说每次都会执行目标方法;发现大于等于5000的随机数都存入缓存汇总了;而小
           于5000的随机数则没有。

allEntries

        此属性主要出现在@CacheEvict注解中,表示是否清除指定命名空间中的所有数据,默认为false。

beforeInvocation

        此属性主要出现在@CacheEvict注解中,表示 是否在目标方法执行前使 此注解生效。 默认为false,即:目标方法执行完毕后此注解生效。

缓存注解使用在返回值为viod方法上的测试

结论是缓存注解作用于void方法上,仍然会向缓存中进行存储,不过键值对中的value为null。

实验示例

验证:

 

笔者寄语

        关于Spring缓存注解的其他一些属性、用法等这里就不再一一叙述了,感兴趣的可自行查询相关资料或阅读源码进行测试

 

^_^ 如有不当之处,欢迎指正

^_^ 测试代码托管链接 
               https://github.com/JustryDeng/CommonRepository

^_^ 本文已经被收录进《程序员成长笔记(二)》,笔者JustryDeng

  • 36
    点赞
  • 140
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
Spring Boot中,你可以使用`@Cacheable`注解来启用缓存功能,并且可以与Redis集成来实现缓存。 `@Cacheable`注解可以应用在方法上,用于指示Spring在调用此方法之前,首先从缓存中查找对应的数据。如果缓存中有数据,则直接返回缓存中的数据,不再执行方法体内的代码。如果缓存中没有数据,则会执行方法体内的代码,并将返回值存储到缓存中。 要使用`@Cacheable`注解,你需要在启动类上添加`@EnableCaching`注解来启用缓存功能。此外,还需要配置Redis作为缓存的存储介质。 首先,引入依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 接下来,在`application.properties`或`application.yml`中配置Redis连接信息: ```yaml spring.redis.host=your_redis_host spring.redis.port=your_redis_port ``` 然后,在需要使用缓存的方法上添加`@Cacheable`注解,指定缓存的名称: ```java @Cacheable("myCache") public String getData(String key) { // 从数据库或其他数据源获取数据的逻辑 } ``` 以上示例中,方法`getData()`会先从名为`myCache`的缓存中查找数据,如果找到则直接返回缓存中的数据;如果没有找到,则执行方法体内的代码,并将返回值缓存起来。 注意:为了使`@Cacheable`注解生效,需要在启动类上添加`@EnableCaching`注解。 这样,你就可以在Spring Boot中使用Redis缓存注解来提高应用的性能了。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值