Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >SpringCache完整案例介绍

SpringCache完整案例介绍

作者头像
用户4919348
发布于 2019-11-29 02:11:13
发布于 2019-11-29 02:11:13
85100
代码可运行
举报
文章被收录于专栏:波波烤鸭波波烤鸭
运行总次数:0
代码可运行

  Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager 接口来统一不同的缓存技术;并支持使用JCache(JSR-107)注解简化我们开发;Cache接口为缓存的组件规范定义,包含缓存的各种操作集合;Cache接口下Spring提供了各种xxxCache的实现;如RedisCacheEhCacheCache ,ConcurrentMapCache等;本文我们就来介绍下SpringCache的具体使用。

一、缓存中的重要概念

注解

说明

Cache

缓存接口,定义缓存操作。实现有:RedisCache、EhcacheCache、ConcurrentMapCache等

CacheManager

缓存管理器,管理各种缓存组件

@Cacheable

注意针对方法配置,能够根据方法的请求参数对其进行缓存

@CacheEvict

清空缓存

@CachePut

保证方法被调用,又希望结果被缓存。与@Cacheable区别在于是否每次都调用方法,常用于更新

@EnableCaching

开启基于注解的缓存

keyGenerator

缓存数据时key生成策略

serialize

缓存数据时value序列化策略

@CacheConfig

统一配置类的缓存注解属性

@Cacheable/@CachePut/@CacheEvict 主要的参数

属性

说明

value

缓存的名称,在 spring 配置文件中定义,必须指定至少一个 例如:@Cacheable(value=”mycache”) 或者@Cacheable(value={”cache1”,”cache2”}

key

缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 例如:@Cacheable(value=”testcache”,key=”#id”)

condition

缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存/清除缓存例如:@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

unless

否定缓存。当条件结果为TRUE时,就不会缓存@Cacheable(value=”testcache”,unless=”#userName.length()>2”)

allEntries (@CacheEvict )

是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存 例如: @CachEvict(value=”testcache”,allEntries=true)

beforeInvocation(@CacheEvict)

是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存例如:@CachEvict(value=”testcache”,beforeInvocation=true)

二、SpEL上下文数据

Spring Cache提供了一些供我们使用的SpEL上下文数据,下表直接摘自Spring官方文档

名称

位置

描述

示例

methodName

root对象

当前被调用的方法名

#root.methodname

method

root对象

当前被调用的方法

#root.method.name

target

root对象

当前被调用的目标对象实例

#root.target

targetClass

root对象

当前被调用的目标对象的类

#root.targetClass

args

root对象

当前被调用的方法的参数列表

#root.args[0]

caches

root对象

当前方法调用使用的缓存列表

#root.caches[0].name

Argument Name

执行上下文

当前被调用的方法的参数,如findArtisan(Artisan artisan),可以通过#artsian.id获得参数

#artsian.id

result

执行上下文

方法执行后的返回值(仅当方法执行后的判断有效,如 unless cacheEvict的beforeInvocation=false)

#result

注意

  1. 当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性。 如   @Cacheable(key = “targetClass + methodName +#p0”)
  2. 使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”。 如:   @Cacheable(value=“users”, key="#id")   @Cacheable(value=“users”, key="#p0")

三、SpringCache的使用

1.导入依赖

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

2.然后在启动类注解@EnableCaching开启缓存

3.创建业务类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.dpb.springboot.service;

import com.dpb.springboot.pojo.User;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * @program: springboot-13-cache
 * @description:
 * @author: 波波烤鸭
 * @create: 2019-11-27 21:25
 */
@Service
public class UserService {

    /**
     * @Cacheable注解会先查询是否已经有缓存,有会使用缓存,没有则会执行方法并缓存
     * 此处的User实体类一定要实现序列化public class User implements Serializable,否则会报java.io.NotSerializableException异常。
     * @param userName
     * @return
     */
    @Cacheable(value = "userCache" , key = "#userName")
    public User getUserByName(String userName){
        System.out.println("数据库查询...." + userName);
        return getFromDB(userName);
    }

    /**
     * 清除一条记录
     * @param user
     */
    @CacheEvict(value = "userCache",key = "#user.name")
    public void updateUser(User user){
        System.out.println("数据更新了。。。。数据库");
        updateDB(user);
    }

    /**
     * allEntries:是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存
     * beforeInvocation:是否在方法执行前就清空,缺省为 false,如果指定为 true,
     *          则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存
     */
    @CacheEvict(value = "userCache",allEntries = true,beforeInvocation = true)
    public void reload(){
        //
    }

    private User getFromDB(String userName){
        System.out.println("查询数据库..." + userName);
        return new User(666,userName);
    }

    private void updateDB(User user){
        System.out.println("更新数据..." + user.getName());
    }
}

4.创建缓存实现类

  我们自定义一个基于内存的缓存实现 Cache接口,并实现相关的方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.dpb.springboot.cache;

import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;

import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @program: springboot-13-cache
 * @description:
 * @author: 波波烤鸭
 * @create: 2019-11-27 21:32
 */
public class MyCache implements Cache {
    // 缓存的 key
    private String name;

    // 保存缓存数据的容器
    private Map<String,Object> store = new ConcurrentHashMap<>();

    public MyCache() {
    }

    public MyCache(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    /**
     * 返回数据容器
     * @return
     */
    @Override
    public Object getNativeCache() {
        return store;
    }

    /**
     * 返回缓存数据
     * @param key
     * @return
     */
    @Override
    public ValueWrapper get(Object key) {
        ValueWrapper result = null;
        Object thevalue = store.get(key);

        if(thevalue != null){
            result = new SimpleValueWrapper(thevalue);
            System.out.println("执行了缓存查询...命中" + key);
        }else{
            System.out.println("执行了缓存查询...没有命中" + key);
        }
        return result;
    }

    /**
     * 返回缓存数据  基于泛型
     * @param key
     * @param aClass
     * @param <T>
     * @return
     */
    @Override
    public <T> T get(Object key, Class<T> aClass) {
        return aClass.cast(store.get(key));
    }

    @Override
    public <T> T get(Object o, Callable<T> callable) {
        return null;
    }


    /**
     * 保存缓存数据
     * @param o
     * @param o1
     */
    @Override
    public void put(Object o, Object o1) {
        //
        System.out.println("数据缓存了..." + o);
        store.put((String)o,o1);
    }

    /**
     * 清除一条缓存数据
     * @param key
     */
    @Override
    public void evict(Object key) {
        System.out.println("移走了元素:" + key);
        store.remove(key);
    }

    /**
     * 清空所有的数据
     */
    @Override
    public void clear() {
        store.clear();
    }
}

5.配置缓存管理器

Spring的配置文件中如下配置

6.测试代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.dpb.springboot;

import com.dpb.springboot.pojo.User;
import com.dpb.springboot.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class Springboot13CacheApplicationTests {

    @Autowired
    private UserService service ;

    @Test
    void contextLoads() {
        System.out.println("第一次查询...");
        service.getUserByName("hello");
        System.out.println("第二次查询...");
        service.getUserByName("hello");
        System.out.println("*************");

        // 更新记录
        User user1 = service.getUserByName("user1");
        // 开始更新其中一个
        user1.setId(1111);
        service.updateUser(user1);
        // 更新后再查询
        service.getUserByName("user1");
        // 再次查询
        service.getUserByName("user1");
        // 更新所有
        service.reload();
        System.out.println("清空了所有的缓存...");

        service.getUserByName("user1");
        service.getUserByName("user2");

        service.getUserByName("user1");
        service.getUserByName("user2");
    }

}

测试结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
第一次查询...
执行了缓存查询...没有命中hello
数据库查询....hello
查询数据库...hello
数据缓存了...hello
第二次查询...
执行了缓存查询...命中hello
*************
执行了缓存查询...没有命中user1
数据库查询....user1
查询数据库...user1
数据缓存了...user1
数据更新了。。。。数据库
更新数据...user1
移走了元素:user1
执行了缓存查询...没有命中user1
数据库查询....user1
查询数据库...user1
数据缓存了...user1
执行了缓存查询...命中user1
清空了所有的缓存...
执行了缓存查询...没有命中user1
数据库查询....user1
查询数据库...user1
数据缓存了...user1
执行了缓存查询...没有命中user2
数据库查询....user2
查询数据库...user2
数据缓存了...user2
执行了缓存查询...命中user1
执行了缓存查询...命中user2

搞定

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/11/28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
一起来学 SpringBoot 2.x | 第十篇:使用 Spring Cache 集成 Redis
1. 特点2. 使用前后3. 添加依赖4. 属性配置5. 具体编码5.1 实体类5.2 定义接口5.3 主函数5.4 测试5.5 根据条件操作缓存5.6 注解介绍6. 总结7. 说点什么
芋道源码
2019/10/29
5360
cacheable更新_详解Spring缓存注解@Cacheable,@CachePut , @CacheEvict使用
@Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
全栈程序员站长
2022/11/16
4.7K0
Spring缓存注解@Cacheable、@CacheEvict、@CachePut
@Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
似水的流年
2020/08/25
2.2K0
springboot中的cache(二)
原理:在 SpringBoot 的 Cache 中,会默认使用 SimpleCacheManager, 生成一个 KeyGenerator(),将数据保存在 ConcurrentMap<Object, Object>中
润森
2019/12/25
5540
springboot-cache的简单使用
Spring Cache 对 Cahce 进行了抽象,提供了 @Cacheable、@CachePut、@CacheEvict 等注解。Spring Boot 应用基于 Spring Cache,既提供了基于内存实现的缓存管理器,可以用于单体应用系统,也集成了 Redis 等缓存服务器,可以用于大型系统或者分布式系统。
宁在春
2022/10/31
8910
springboot-cache的简单使用
springboot cache 缓存
使用springboot的cache功能: 1.在启动类上加注解@enableCaching,启用缓存 2.在需要缓存的方法上加入对应的注解,具体如下: /* * 1.@Cacheable(cacheNames = "car", key = "#name") * 将方法的返回值 保存 在缓存“car”中,键由key指定,值是方法的返回值 * 2.@CachePut(cacheNames = "car", key = "#car.name") * 使用方法的返回值 更新 缓存“car”中,键为key的
yawn
2018/03/14
8780
springboot使用cache缓存
Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口来统一不同的缓存技术;并支持使用JCache(JSR-107)注解简化我们开发;
吟风者
2019/07/25
1.1K0
一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
Spring3.1 引入了激动人心的基于注解( annotation)的缓存( cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 Redis),而是一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种 annotation,即能够达到缓存方法的返回对象的效果。
battcn
2018/08/03
7220
Spring 整合 Redis
这里配置就完成了。可以直接在service方法上面开启注解: 有4个注解@Cacheable,@CachePut , @CacheEvict,@CacheConfig @Cacheable、@CachePut、@CacheEvict 注释介绍 @Cacheable 作用和配置方法 @Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存 @Cacheable 主要的参数 value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个例如:这里和上面的name 的value对应,楼主这里写的是common @Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”} key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合例如: @Cacheable(value=”testcache”,key=”#userName”) condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存例如: @Cacheable(value=”testcache”,condition=”#userName.length()>2”)
試毅-思伟
2018/09/06
5590
(11)SpringBoot整合EhCache做缓存
EhCache 简介:EhCache 是一个纯Java的进程内缓存框架,是Hibernate中默认的CacheProvider;其缓存的数据可以存放在内存里面,也可以存放在硬盘上;其核心是CacheManager,一切Ehcache的应用都是从CacheManager开始的;它是用来管理Cache(缓存)的,一个应用可以有多个CacheManager,而一个CacheManager下又可以有多个Cache;Cache内部保存的是一个个的Element,而一个Element中保存的是一个key和value的配对,相当于Map里面的一个Entry。
IT云清
2022/05/07
1.4K0
Spring Boot 2.X(七):Spring Cache 使用
Spring Cache 提供了 @Cacheable 、@CachePut 、@CacheEvict 、@Caching 等注解,在方法上使用。通过注解 Cache 可以实现类似事务一样、缓存逻辑透明的应用到我们的业务代码上,且只需要更少的代码。 核心思想:当我们调用一个方法时会把该方法的参数和返回结果最为一个键值对存放在缓存中,等下次利用同样的参数来调用该方法时将不会再执行,而是直接从缓存中获取结果进行返回。
朝雾轻寒
2019/10/18
1K0
玩转Spring Cache --- @Cacheable/@CachePut/@CacheEvict注解的原理深度剖析和使用【享学Spring】
上篇文章介绍了@EnableCaching,用它来开启Spring对缓存注解的支持。本篇文章将继续分析Spring Cache,并且讲解的是我们最为关心的:缓存注解实操方面的原理支持和使用。
YourBatman
2019/09/03
11.9K1
玩转Spring Cache --- @Cacheable/@CachePut/@CacheEvict注解的原理深度剖析和使用【享学Spring】
重学SpringBoot系列之Spring cache详解
使用缓存是一个很“高性价比”的性能优化方式,尤其是对于有大量重复查询的程序来说。通常来说,在WEB后端应用程序来说,耗时比较大的往往有两个地方:一个是查数据库,一个是调用其它服务的API(因为其它服务最终也要去做查数据库等耗时操作)。
大忽悠爱学习
2021/12/07
1.8K0
重学SpringBoot系列之Spring cache详解
Spring缓存注解@Cacheable、@CacheEvict、@CachePut使用
从3.1开始,Spring引入了对Cache的支持。其使用方法和原理都类似于Spring对事务管理的支持。Spring Cache是作用在方法上的,其核心思想是这样的:当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值对存放在缓存中,等到下次利用同样的参数来调用该方法时将不再执行该方法,而是直接从缓存中获取结果进行返回。所以在使用Spring Cache的时候我们要保证我们缓存的方法对于相同的方法参数要有相同的返回结果。
用户7353950
2022/05/10
2.6K0
springboot高级特性-缓存
springboot的缓存有以下层级关系 CachingProvider 缓存提供者 —>管理和控制多个CacheManager---->管理和控制多个唯一命名的cache----->存储在cache中的key-value对-------->Expiry 每一个存储在cache中的条目有一个有效期
暴躁的程序猿
2022/03/23
4330
springboot高级特性-缓存
Spring思维导图,让Spring不再难懂(cache篇)
关于缓存 缓存是实际工作中非常常用的一种提高性能的方法。而在java中,所谓缓存,就是将程序或系统经常要调用的对象存在内存中,再次调用时可以快速从内存中获取对象,不必再去创建新的重复的实例。这样做可以减少系统开销,提高系统效率。 在增删改查中,数据库查询占据了数据库操作的80%以上,而非常频繁的磁盘I/O读取操作,会导致数据库性能极度低下。而数据库的重要性就不言而喻了: 数据库通常是企业应用系统最核心的部分 数据库保存的数据量通常非常庞大 数据库查询操作通常很频繁,有时还很复杂 在系统架构的不同层级之间,为
java思维导图
2018/03/15
8010
Spring思维导图,让Spring不再难懂(cache篇)
springBoot高级
1、在springBoot中可以使用注解式开发缓存,默认没有开启缓存中间件,那么使用的就是存储在Map中的原理,但是我们还可以配置自己的缓存中间件,比如redis
爱撒谎的男孩
2019/12/31
6840
Spring Cache+Redis缓存数据
  我们知道内存的读取速度远大于硬盘的读取速度。当需要重复地获取相同数据时,一次一次地请求数据库或者远程服务,导致在数据库查询或远程方法调用上消耗大量的时间,最终导致程序性能降低,这就是数据缓存要解决的问题。
别团等shy哥发育
2023/02/25
1.1K0
Spring Cache+Redis缓存数据
springboot cache 基本使用
为什么使用缓存? 比如一个复杂的计算结果,一次数据库访问取得的数据等耗时耗资源的数据就能放入缓存,目的就是为了节省开销,我们要用有限的资源(CPU,内存,带宽等等)尽量做最多的事情。
smallmayi
2022/05/12
6090
springboot cache 基本使用
【SpringCache】快速入门 通俗易懂
Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
陶然同学
2023/12/09
2640
【SpringCache】快速入门 通俗易懂
相关推荐
一起来学 SpringBoot 2.x | 第十篇:使用 Spring Cache 集成 Redis
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验