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

Terwer Green

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

  • 开源框架

    • MyBatis

      • JDBC的问题分析
      • 自定义持久层框架的设计思路
      • 自定义持久层框架的代码实现一
      • 自定义持久层框架的代码实现二
      • 使用getMapper方式对自定义持久层框架进行优化
      • MyBatis的基本介绍及优势
      • MyBatis的基本使用
      • Mybatis基本流程及配置文件解析
      • MyBatis复杂映射开发之一对一查询
      • MyBatis复杂映射开发之一对多查询
      • MyBatis复杂映射开发之多对多查询
      • MyBatis常用注解及基本增删改查的注解实现
      • MyBatis的注解实现复杂映射开发
      • MyBatis缓存的概念
      • MyBatis的一级缓存
      • MyBatis的二级缓存
      • MyBatis的二级缓存整合redis
      • MyBatis-RedisCache源码分析
        • 回顾
        • 源码分析
  • Linux

  • Struts2

  • Hibernate

  • Webservice

  • 分布式

  • 分布式框架

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

MyBatis-RedisCache源码分析

# 回顾

在前面,我们通过 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());
        }
    }
}
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)
#通过#方法#分析#实现#读取
上次更新: 2023/02/22, 13:47:25
MyBatis的二级缓存整合redis
Paralle_Desktop安装CentOS7

← MyBatis的二级缓存整合redis Paralle_Desktop安装CentOS7→

最近更新
01
解决css部分border被圆角切掉之后圆角的边框消失问题
03-18
02
使用TypeScript开发一个自定义的Node-js前端开发脚手架
03-08
03
Github-Actions使用release-please实现自动发版
03-06
更多文章>
Theme by Vdoing | Copyright © 2011-2023 Terwer Green | MIT License | 粤ICP备2022020721号-1 | 百度统计
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式