首页 > 数据库 >MyBatis-RedisCache源码分析

MyBatis-RedisCache源码分析

时间:2023-02-20 22:14:29浏览次数:36  
标签:RedisConfig Cache private RedisCache public 源码 MyBatis id

回顾

在前面,我们通过 redis​ 集成了 MyBatis​ 的二级缓存,440.MyBatis的二级缓存整合redis ,接下来,我们来分析一下 RedisCache​ 的源码。

源码分析

RedisCache 主要是通过实现 Cache 接口来做的。数据存储和获取主要是通过操作 jedis 来实现。

public final class RedisCache implements Cache {
    private final ReadWriteLock readWriteLock = new DummyReadWriteLock();
    private String id;
    private static JedisPool pool;

    public RedisCache(String id) {
        if (id == null) {
            throw new IllegalArgumentException("Cache instances require an ID");
        } else {
            this.id = id;
            RedisConfig redisConfig = RedisConfigurationBuilder.getInstance().parseConfiguration();
            pool = new JedisPool(redisConfig, redisConfig.getHost(), redisConfig.getPort(), redisConfig.getConnectionTimeout(), redisConfig.getSoTimeout(), redisConfig.getPassword(), redisConfig.getDatabase(), redisConfig.getClientName());
        }
    }
}

RedisCache 在 MyBatis 启动的时候由 MyBatis 的 CacheBuilder​ 构建,构建的方式就是调用 Cache​ 实现类的带 id​ 参数的构造方法。

// CacheBuilder.java

public Cache build() {
    setDefaultImplementations();
    Cache cache = newBaseCacheInstance(implementation, id);
    setCacheProperties(cache);
}

private Cache newBaseCacheInstance(Class<? extends Cache> cacheClass, String id) {
    Constructor<? extends Cache> cacheConstructor = getBaseCacheConstructor(cacheClass);
    try {
        return cacheConstructor.newInstance(id);
    } catch (Exception e) {
        throw new CacheException("Could not instantiate cache implementation (" + cacheClass + "). Cause: " + e, e);
    }
}

RedisCache​ 的构造方法中,调用了 RedisConfigurationBuilder​ 来常见 RedisConfig​ 对象,并通过 RedisConfig​ 对象来创建 Jedis​ 。

RedisConfig​ 继承了 JedisPoolConfig​ ,并定义了一些属性来读取配置。

public class RedisConfig extends JedisPoolConfig {
    private String host = "localhost";
    private int port = 6379;
    private int connectionTimeout = 2000;
    private int soTimeout = 2000;
    private String password;
    private int database = 0;
    private String clientName;
}

RedisConfig​ 是由 RedisConfigurationBuilder​​ 构建的,这个类的主要方法是 parseConfiguration

public RedisConfig parseConfiguration(ClassLoader classLoader) {
    Properties config = new Properties();
    InputStream input = classLoader.getResourceAsStream(this.redisPropertiesFilename);
    if (input != null) {
        try {
            config.load(input);
        } catch (IOException var12) {
            throw new RuntimeException("An error occurred while reading classpath property '" + this.redisPropertiesFilename + "', see nested exceptions", var12);
        } finally {
            try {
                input.close();
            } catch (IOException var11) {
            }

        }
    }

    RedisConfig jedisConfig = new RedisConfig();
    this.setConfigProperties(config, jedisConfig);
    return jedisConfig;
}

该方法从 Resource​ 读取一个 redis.properties​ 文件,其结构如下:

host=localhost
port=6379
password=123456
database=0

读取完成之后将内容设置到 RedisConfig 对象中。

接下来,RedisCache 使用 RedisCo 创建 Jedis。在 RedisCache 中,实现了一个简单的模板方法来操作 redis:

private Object execute(RedisCallback callback) {
    Jedis jedis = pool.getResource();

    Object var3;
    try {
        var3 = callback.doWithRedis(jedis);
    } finally {
        jedis.close();
    }

    return var3;
}

目标接口为 RedisCallback,该接口定义了一个简单的 doWithRedis 方法用来进行 redis 相关操作:

public interface RedisCallback {
    Object doWithRedis(Jedis var1);
}

接下来,我们分析一下 Cache 中的两个重要方法 putObject()和 getObject()

public void putObject(final Object key, final Object value) {
    this.execute(new RedisCallback() {
        public Object doWithRedis(Jedis jedis) {
            jedis.hset(RedisCache.this.id.toString().getBytes(), key.toString().getBytes(), SerializeUtil.serialize(value));
            return null;
        }
    });
}
public Object getObject(final Object key) {
    return this.execute(new RedisCallback() {
        public Object doWithRedis(Jedis jedis) {
            return SerializeUtil.unserialize(jedis.hget(RedisCache.this.id.toString().getBytes(), key.toString().getBytes()));
        }
    });
}

可以看出来,MyBatis-RedisCache 采用的是 redis 的 hash​ 结构来存储数据,把 Cache 的 id​ 作为 hash 的 key​(Cache 的 id 在 Mapper 中是 namspace),缓存和读取之前通过 SerializeUtil 进行序列化或者反序列化

标签:RedisConfig,Cache,private,RedisCache,public,源码,MyBatis,id
From: https://www.cnblogs.com/tangyouwei/p/mybatisrediscache-source-code-analysis-1tshmo.html

相关文章

  • mybatis
    mybatis3增加注解@SelectProvidermybatis3中增加了使用注解来配置Mapper的新特性,其中@Provider的使用方式较为复杂。@provide主要分为四种:@InsertProvider@DeletePro......
  • MyBatisPlus(springBoot版)-尚硅谷
    Pom.xml<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"......
  • ScheduledThreadPoolExecutor的基本使用和源码解读
    1基本使用ScheduledThreadPoolExecutor是一种特殊的线程池,它可以执行延迟任务和定时任务。首先,通常会在全局范围内创建线程池对象,可以是静态变量,或者Spring单例对象:Thr......
  • Java集合Map接口详解——含源码分析
    前言关于集合中的Collection我们已经讲完了,接下来我们一起来看集合中的另一个大类:MapMap的实现类首先Map是一个接口,是一对键值对来存储信息的,K为key键,V为value值HashMapimpo......
  • 【代理】【二】代理源码解析-JDK动态代理使用及源码分析
    1 前言本节我们讲一下动态代理的实现过程,并且从源码分析下产生过程。看之前先简单看几个基础知识:函数接口BiFunction<T,U,R>:Rapply(Tt,Uu);就是参数是T、U......
  • DateTimePicker 日期时间选择器 + mybatis-plus 传参后端查询 传值自定义list,后端再
    前端<el-form-itemlabel="创建时间"prop="extendate"><el-date-pickerv-model="queryParams.extendate"......
  • 【代理】【一】代理源码解析-导读
    1 什么是代理代理是指给某一个对象提供一个代理对象,代理对象持有原对象的引用。一句话通过代理对象增强原对象的功能,比如在原对象调用一个方法的前后进行日志、事务操作......
  • 五、MyBatis的多表操作
    一对一查询一对一查询的模型用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户一对一......
  • VPP 2110版本源码编译安装
    原文地址:https://www.cnblogs.com/liqinglucky/p/vpp.html一介绍官方文档:VPP/WhatisVPP?-fd.ioVPP平台是一个提供了交换机/路由器(switch/router)开箱即用(out-of......
  • 集群机制:注册表同步以及高可用源码剖析
    1在完成服务注册之后,会将注册信息同步给群里中的其他节点,以实现高可用,续约,服务更新,下线都是一样的操作2拿到集群中其他节点的url信息,同步数据3执行批处理任务,ba......