Spring Boot 集成 Redis

使用的框架

  • Spring Boot
  • Spring Data Redis

RedisTemplates 中封装了很多对象类,我们通过对于类的一个操作,能够实现数据的填充。如

@Override
public ValueOperations<K, V> opsForValue() {
	return valueOps;
}

Redis 中的数据是以 key-value 形式的,ValueOperations<K, V> 设计约等于将 key-value 封装成了一个对象。

解析一个基于 AbstractOperations 对象类的序列化与反序列化操作

Redis 会给追加进入的数据进行自动的序列化,在首部进行字符的追加,在存入时会进行序列化,在读取时会进行反序列化。

这个是为什么呢?不是 Redis 的操作,而是我们使用的 Spring Data Redis 进行的操作。在 Java 程序中,Spring Data Redis 提供了丰富的与 Redis 进行操作的接口和封装类。我们使用 Redis 的缓存功能时,我们需要操作提供给我们的接口 RedisTemplate,而 RedisTemplate 中的实现操作类 DefaultValueOperations<K, V>

继承的抽象基类 AbstractOperations 中的源码有非常直观的表现。

以任意一个存取函数为例。这里是取函数 get(),那么我们以 Java 程序的角度为例,存在数据库里的数据库

@Override
public V get(Object key) {

    return execute(new ValueDeserializingRedisCallback(key) {

        @Override
        protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
            return connection.get(rawKey);
        }
    }, true);
}

首先,这里做了有且仅有的一个操作,执行 execute(RedisCallBack<T> action, boolean exposeConnection, boolean pipeline) 函数,实例化父类中的内部类 ValueDeserializingRedisCallback,并将 key 值存入其中。也就是说,在 execute() 函数之前,我们已经实例化了具体的操作对象。这是一个解耦设计,使 execute 函数可以专注于逻辑的处理,而并非对对象的控制操作管理。

execute() 函数

位于父类中的 execute 函数的解释如下。总的来说,它是一个执行操作对象的函数。在这里有一个回调设计的布尔开关,这个非常重要,是后续实现对对象中 doInRedis 函数执行的启动开关。

在可公开或不可公开的连接中执行给定的操作对象。此外,该连接可以进行流水线处理。请注意,流水线处理的结果将被丢弃(因此适用于只写场景)
形参:
action – 要执行的回调对象
exposeConnection – 是否强制向回调代码公开原生 Redis 连接
pipeline – 是否将连接进行流水线处理

类型形参:<T> – 返回类型
返回值:操作返回的对象

@Nullable
public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {

  Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
  Assert.notNull(action, "Callback object must not be null");

  RedisConnectionFactory factory = getRequiredConnectionFactory();
  RedisConnection conn = RedisConnectionUtils.getConnection(factory, enableTransactionSupport);

  try {

    boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);
    RedisConnection connToUse = preProcessConnection(conn, existingConnection);

    boolean pipelineStatus = connToUse.isPipelined();
    if (pipeline && !pipelineStatus) {
      connToUse.openPipeline();
    }

    RedisConnection connToExpose = (exposeConnection ? connToUse : createRedisConnectionProxy(connToUse));
    T result = action.doInRedis(connToExpose);

    // close pipeline
    if (pipeline && !pipelineStatus) {
      connToUse.closePipeline();
    }

    return postProcessResult(result, connToUse, existingConnection);
  } finally {
    RedisConnectionUtils.releaseConnection(conn, factory, enableTransactionSupport);
  }
}

我们可以看到一个非常整洁自洽的 RedisCallBack<T> 的完整生命周期。在这个 excute() 函数中,我们终于第一次看到了顾名思义的 CallBack(回调)。在整个 exeute() 函数内部,唯一一次调用实例对象的操作(Assert 除外)是 :

T result = action.doInRedis(connToExpose);

这个 doIndedis 函数在我们的情境中,实际上具体的实现如下,可以看到,在这里它最终调用了反序列化函数,并最终返回该结果作为 result。

public final V doInRedis(RedisConnection connection) {
  byte[] result = inRedis(rawKey(key), connection);
  return deserializeValue(result);
}

execute 函数还负责了 close 连接池的一系列收尾操作。在这里基本完成了一个 get 函数的请求。

内部类 ValueDeserializingRedisCallBack 详细代码
// utility methods for the template internal methods
abstract class ValueDeserializingRedisCallback implements RedisCallback<V> {
	private Object key;

	public ValueDeserializingRedisCallback(Object key) {
		this.key = key;
	}

	public final V doInRedis(RedisConnection connection) {
		byte[] result = inRedis(rawKey(key), connection);
		return deserializeValue(result);
		}

	@Nullable
	protected abstract byte[] inRedis(byte[] rawKey, RedisConnection connection);
}

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇