远方的灯塔 - 专注于服务端技术分享 远方的灯塔 - 专注于服务端技术分享
首页
  • Java SE
  • Struts2
  • Hibernate
  • MyBatis
  • JAX-WS
  • 并发
  • 分布式
  • Git
  • 《C程序设计语言》
心情随笔
  • 文章分类
  • 文章标签
  • 文章归档
友情链接
关于我
GitHub (opens new window)

Terwer Green

一个后端老菜鸟
首页
  • Java SE
  • Struts2
  • Hibernate
  • MyBatis
  • JAX-WS
  • 并发
  • 分布式
  • Git
  • 《C程序设计语言》
心情随笔
  • 文章分类
  • 文章标签
  • 文章归档
友情链接
关于我
GitHub (opens new window)
  • MyBatis

    • 解析原生JDBC开发问题与优化方案
    • 自定义持久层框架的设计思路
    • 自定义持久层框架的代码实现一
    • 自定义持久层框架的代码实现二
    • 使用getMapper方式对自定义持久层框架进行优化
    • MyBatis的基本介绍及优势
    • MyBatis的基本使用
    • Mybatis基本流程及配置文件解析
    • MyBatis复杂映射开发之一对一查询
    • MyBatis复杂映射开发之一对多查询
    • MyBatis复杂映射开发之多对多查询
    • MyBatis常用注解及基本增删改查的注解实现
    • MyBatis的注解实现复杂映射开发
    • MyBatis缓存的概念
    • 深度剖析MyBatis的一级缓存
    • 深度剖析MyBatis的二级缓存
    • MyBatis的二级缓存整合redis
    • MyBatis-RedisCache源码分析
      • 回顾
      • 源码分析
    • MyBatis机制介绍与原理
    • 自定义MyBatis插件
    • 插件源码进一步分析与pageHelper分页插件介绍
    • 通用 Mapper 封装
    • 深入剖析MyBatis的架构原理
  • 《设计模式》

  • 后端开发
  • MyBatis
terwer
2023-02-20
目录

MyBatis-RedisCache源码分析

RedisCache 是 MyBatis 的二级缓存实现类,通过操作 jedis 来实现数据的存储和获取。构造方法中通过 RedisConfigurationBuilder 创建 RedisConfig 对象,并使用该对象创建 Jedis 连接池。

# 回顾

在前面,我们通过 redis​ 集成了 MyBatis​ 的二级缓存,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());
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

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);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在 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;
}
1
2
3
4
5
6
7
8
9

​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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

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

host=localhost
port=6379
password=123456
database=0
1
2
3
4

读取完成之后将内容设置到 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;
}
1
2
3
4
5
6
7
8
9
10
11
12

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

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

接下来,我们分析一下 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;
        }
    });
}
1
2
3
4
5
6
7
8
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()));
        }
    });
}
1
2
3
4
5
6
7

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

‍

编辑 (opens new window)
#通过#方法#分析#实现#读取#redis#cache#mybatis
上次更新: 2024/06/13, 05:26:42
MyBatis的二级缓存整合redis
MyBatis机制介绍与原理

← MyBatis的二级缓存整合redis MyBatis机制介绍与原理→

最近更新
01
深入剖析MyBatis的架构原理
12-04
02
通用 Mapper 封装
10-09
03
插件源码进一步分析与pageHelper分页插件介绍
10-09
更多文章>
Theme by Vdoing | Copyright © 2011-2024 Terwer Green | MIT License | 粤ICP备2022020721号-1 | 百度统计
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式