IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 【Spring】@Cacheable 注解的使用及原理 -> 正文阅读

[Java知识库]【Spring】@Cacheable 注解的使用及原理

@Cacheable注解

本地缓存

在很多时候,需要对数据库中查询出来的数据进行缓存操作,避免频繁的查库给数据库带来不必要的压力,所以诞生了缓存。
常见的缓存中间件有 Redis、Memcache、Ehcache 等。比如常用的 Redis 其实是一种常见的 K-V 非关系型数据库,处理很多数据的缓存时,需要经过网络 IO 才能提供服务。与网络缓存对应的,就是本地缓存。其中比较经典的本地缓存实现方式,有:

ConcurrentHashMap、Guava Cache、Caffeine、Encache

参考文档:本地缓存:为什么要用本地缓存?用它会有什么问题?_Gimtom的博客-CSDN博客_本地缓存

  • 本地缓存基于本地环境的内存,访问速度非常快,对于一些变更频率低、实时性要求低的数据,可以放在本地缓存中,提升访问速度。
  • 使用本地缓存能够减少和 Redis 类的远程缓存间的数据交互,减少网络 I/O 开销,降低这一过程中在网络通信上的耗时。

其实在 Spring 中,已经有了对应的缓存实现类。Spring 从 3.1 开始就引入了对 Cache 的支持。定义了 org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 接口来统一不同的缓存技术。
其使用方法和原理都类似于 Spring 对事务管理的支持。Spring Cache 是作用在方法上的,其核心思想是,当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值对存在缓存中。

使用步骤

一、导入依赖

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

二、在启动类进行相关的配置

/**
* 开启缓存注解驱动,否则后面使用的缓存都是无效的
*/
@EnableCaching
@SpringBootApplication
public class DemoApplication {

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

}

或者执行一个配置类

/**
 * 或者进行 CacheConfig 一类的配置类
 * @author Real
 * Date: 2022/9/7 20:01
 */
@Slf4j
@EnableCaching
@Configuration
public class CacheConfig {
    @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() + "]";
            }
        };
    }
}

三、在需要使用缓存的地方使用对应的注解

一般在 ServiceImpl 类上使用,或者在对应的方法上使用。

@Service
@CacheConfig(cacheNames = "deptCache", keyGenerator = "myKeyGenerator")
public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Department>
        implements DepartmentService {

    @Autowired
    private DepartmentMapper departmentMapper;

    @Override
    @Cacheable(cacheNames = "deptCache")
    public List<Department> getAllDept() {
        return departmentMapper.selectList(Wrappers.emptyWrapper());
    }

    @Override
    @Cacheable(cacheNames = "deptCache", key = "#id")
    public Department getById(Integer id) {
        return departmentMapper.selectById(id);
    }
}

这里需要注意的是:Spring 并不推荐在接口上使用 Cache* 注解

image.png
四、测试使用
第一次访问对应的方法,会使用 Mapper 接口查询数据库数据。
image.png
第二次访问同一个方法时,不走 Mapper 接口调用。
image.png
此外,还可以设置使用缓存的条件,不符合条件的将不会使用缓存。

@Override
@Cacheable(cacheNames = "deptCache", condition = "#id > 10")
public Department getDeptByCondition(Integer id) {
    return departmentMapper.selectById(id);
}

Cache SpEL available metadata

名称位置描述示例
methodNameroot对象当前被调用的方法名#root.methodname
methodroot对象当前被调用的方法#root.method.name
targetroot对象当前被调用的目标对象实例#root.target
targetClassroot对象当前被调用的目标对象的类#root.targetClass
argsroot对象当前被调用的方法的参数列表#root.args[0]
cachesroot对象当前方法调用使用的缓存列表#root.caches[0].name
argumentName执行上下文(avaluation context)当前被调用的方法的参数,如findArtisan(Artisan artisan),可以通过#artsian.id获得参数#artsian.id
result执行上下文(evaluation context)方法执行后的返回值(仅当方法执行后的判断有效,如 unless cacheEvict的beforeInvocation=false)#result

执行分析

在第二次使用到缓存的时候,在 Mapper 调用的方法上打断点,并不会触发 SqlSession 对象的创建和调用。
而在 CacheManager 接口上的 getValue 方法打上断点,却会出现响应:
image.png
真正调用的实现类是 ConcurrentMapCacheManager 实现类。
image.png
这个实现类的代码为:

@Nullable
public Cache getCache(String name) {
    Cache cache = (Cache)this.cacheMap.get(name);
    if (cache == null && this.dynamic) {
        synchronized(this.cacheMap) {
            cache = (Cache)this.cacheMap.get(name);
            if (cache == null) {
                cache = this.createConcurrentMapCache(name);
                this.cacheMap.put(name, cache);
            }
        }
    }
    return cache;
}

可以看到使用了一个简单的 DCL 来实现。创建 Cache 的方法也比较简单:

protected Cache createConcurrentMapCache(String name) {
    SerializationDelegate actualSerialization = this.isStoreByValue() ? this.serialization : null;
    return new ConcurrentMapCache(name, new ConcurrentHashMap(256), this.isAllowNullValues(), actualSerialization);
}

这里使用到了一个 SerializationDelegate 序列化委托对象,这个方法提供了一个方便的委托,具有预先安排的配置状态,可满足常见的序列化需求。

protected ConcurrentMapCache(String name, ConcurrentMap<Object, Object> store,
			boolean allowNullValues, @Nullable SerializationDelegate serialization) {
    super(allowNullValues);
    Assert.notNull(name, "Name must not be null");
    Assert.notNull(store, "Store must not be null");
    this.name = name;
    this.store = store;
    this.serialization = serialization;
}

默认使用一个 capacity 为 256 的 ConcurrentHashMap 对象来存储对应的值。

实现原理

Cache 接口包含缓存的各种操作集合,你操作缓存就是通过这个接口来操作的。 Cache 接口下 Spring 提供了各种 xxxCache 的实现,比如:RedisCache、EhCache、ConcurrentMapCache 等实现类。
CacheManager 定义了创建、配置、获取、管理和控制多个唯一命名的 Cache。这些 Cache 存在于 CacheManager 的上下文中。

public interface CacheManager {
    @Nullable
    Cache getCache(String name);

    Collection<String> getCacheNames();
}

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

  • 确定方法需要被缓存以及他们的缓存策略。
  • 从缓存中读取之前缓存存储的数据。
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 10:59:34  更:2022-09-13 11:03:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 12:57:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码