RedisTemplate和StringRedisTemplate的区别

一.简介

简单的说,RedisTemplateStringRedisTemplate的关系如下:

1.StringRedisTemplateRedisTemplate的子类。

2.StringRedisTemplate的各个序列化策略都是StringRedisSerializer,而RedisTemplate用的是JdkSerializationRedisSerializer

二.RedisTemplate和StringRedisTemplate的代码结构

RedisTemplate类说起。

RedisTemplate类中,定义了这样四个变量:

1
2
3
4
5
6
7
8
@Nullable
private RedisSerializer keySerializer = null;
@Nullable
private RedisSerializer valueSerializer = null;
@Nullable
private RedisSerializer hashKeySerializer = null;
@Nullable
private RedisSerializer hashValueSerializer = null;

分别代表了普通keyvalue,和Hash类型的key,value的序列化策略,可以分别设置。

另外定义变量,用来指定默认的序列化策略:

1
2
@Nullable
private RedisSerializer<?> defaultSerializer;

RedisTemplate类中,定义了afterPropertiesSet()方法,当Spring创建RedisTemplate类的对象时,会调用这个方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public void afterPropertiesSet() {
super.afterPropertiesSet();
boolean defaultUsed = false;
if (this.defaultSerializer == null) {
this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());
}

if (this.enableDefaultSerializer) {
if (this.keySerializer == null) {
this.keySerializer = this.defaultSerializer;
defaultUsed = true;
}

if (this.valueSerializer == null) {
this.valueSerializer = this.defaultSerializer;
defaultUsed = true;
}

if (this.hashKeySerializer == null) {
this.hashKeySerializer = this.defaultSerializer;
defaultUsed = true;
}

if (this.hashValueSerializer == null) {
this.hashValueSerializer = this.defaultSerializer;
defaultUsed = true;
}
}

if (this.enableDefaultSerializer && defaultUsed) {
Assert.notNull(this.defaultSerializer, "default serializer null and not all serializers initialized");
}

if (this.scriptExecutor == null) {
this.scriptExecutor = new DefaultScriptExecutor(this);
}

this.initialized = true;
}

可以看到,在默认情况下,RedisTemplate使用的默认序列化策略是JdkSerializationRedisSerializer。包括RedisTemplate下的keyvaluehash-key,hash-value的序列化,都用这种策略。

再来看看StringRedisTemplate,他作为RedisTemplate的子类,只是修改了序列化策略:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class StringRedisTemplate extends RedisTemplate<String, String> {
public StringRedisTemplate() {
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
this.setKeySerializer(stringSerializer);
this.setValueSerializer(stringSerializer);
this.setHashKeySerializer(stringSerializer);
this.setHashValueSerializer(stringSerializer);
}

public StringRedisTemplate(RedisConnectionFactory connectionFactory) {
this();
this.setConnectionFactory(connectionFactory);
this.afterPropertiesSet();
}

protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
return new DefaultStringRedisConnection(connection);
}
}

以上就是StringRedisTemplate整个类的内容,可以看到,在他的默认构造中,keyvaluehash-keyhash-value都使用的是StringRedisSerializer类作为序列化策略。这也就是StringRedisTemplate和他的父类RedisTemplate的主要区别。

三.序列化策略

更进一步,看一下这个序列化策略是什么。

上面提到的StringRedisSerializerJdkSerializationRedisSerializer都是序列化策略类,他们都实现了一个RedisSerializer<T>接口:

1
2
3
4
5
6
7
public interface RedisSerializer<T> {
@Nullable
byte[] serialize(@Nullable T var1) throws SerializationException;

@Nullable
T deserialize(@Nullable byte[] var1) throws SerializationException;
}

接口表达的意思很简单,两个方法,serialize用于序列化,把对象变为byte数组,deserialize用于反序列化,把byte数组转为对象。

StringRedisSerializer

看看StringRedisSerializer是怎么做的:

1.StringRedisSerializer的构造:

1
2
3
4
5
6
7
8
public StringRedisSerializer() {
this(StandardCharsets.UTF_8);
}

public StringRedisSerializer(Charset charset) {
Assert.notNull(charset, "Charset must not be null!");
this.charset = charset;
}

定义了编码格式,默认UTF_8

2.StringRedisSerializer的serialize和deserialize方法:

1
2
3
4
5
6
7
public String deserialize(@Nullable byte[] bytes) {
return bytes == null ? null : new String(bytes, this.charset);
}

public byte[] serialize(@Nullable String string) {
return string == null ? null : string.getBytes(this.charset);
}

可以看到,StringRedisSerializer采用的是字符串和对应编码下二进制数组之间的转换。

在这种编码格式下,如果我们向redis保存信息,然后用客户端访问Redis时,只要编码格式一致,就能看到保存信息的原文。保存字符串ABC,客户端看到的也是字符串ABC

JdkSerializationRedisSerializer

然后对比看看JdkSerializationRedisSerializer是怎么做的。

1.JdkSerializationRedisSerializer的构造:

1
2
3
4
5
6
7
8
9
10
private final Converter<Object, byte[]> serializer;
private final Converter<byte[], Object> deserializer;

public JdkSerializationRedisSerializer() {
this(new SerializingConverter(), new DeserializingConverter());
}

public JdkSerializationRedisSerializer(ClassLoader classLoader) {
this(new SerializingConverter(), new DeserializingConverter(classLoader));
}

可以看到,JdkSerializationRedisSerializer定义了两个变量,serializer和deserializer,显然是用来序列化和反序列化的,他们两个的类型是一样的,都是Converter接口,只是泛型不同。

Converter接口:

1
2
3
4
5
@FunctionalInterface
public interface Converter<S, T> {
@Nullable
T convert(S source);
}

就一个方法。

另外在JdkSerializationRedisSerializer的构造中,对serializer和deserializer进行了初始化,使用SerializingConverter和DeserializingConverter作为实现类。

2.JdkSerializationRedisSerializer的serialize和deserialize方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object deserialize(@Nullable byte[] bytes) {
if (SerializationUtils.isEmpty(bytes)) {
return null;
} else {
try {
return this.deserializer.convert(bytes);
} catch (Exception var3) {
throw new SerializationException("Cannot deserialize", var3);
}
}
}

public byte[] serialize(@Nullable Object object) {
if (object == null) {
return SerializationUtils.EMPTY_ARRAY;
} else {
try {
return (byte[])this.serializer.convert(object);
} catch (Exception var3) {
throw new SerializationException("Cannot serialize", var3);
}
}
}

其实就是调用了对应Converterconvert方法。

3.关于Converter

既然到这了,就再深入一步,看看SerializingConverter和DeserializingConverter的convert方法。

首先,序列化:

SerializingConverter的相关方法,贴一部分关键的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public SerializingConverter() {
this.serializer = new DefaultSerializer();
}

@Override
public byte[] convert(Object source) {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(1024);
try {
this.serializer.serialize(source, byteStream);
return byteStream.toByteArray();
}
catch (Throwable ex) {
throw new SerializationFailedException("Failed to serialize object using " +
this.serializer.getClass().getSimpleName(), ex);
}
}

可以看到,SerializingConverter类定义了serializer变量,用DefaultSerializer类实现,序列化的方式是调用DefaultSerializerserialize方法:

1
2
3
4
5
6
7
8
9
10
@Override
public void serialize(Object object, OutputStream outputStream) throws IOException {
if (!(object instanceof Serializable)) {
throw new IllegalArgumentException(getClass().getSimpleName() + " requires a Serializable payload " +
"but received an object of type [" + object.getClass().getName() + "]");
}
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(object);
objectOutputStream.flush();
}

DefaultSerializerserialize方法使用了ObjectOutputStream,调用writeObject方法序列化对象。

对应的,反序列化:

DeserializingConverter的convert方法,贴一下相关代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public DeserializingConverter() {
this.deserializer = new DefaultDeserializer();
}

@Override
public Object convert(byte[] source) {
ByteArrayInputStream byteStream = new ByteArrayInputStream(source);
try {
return this.deserializer.deserialize(byteStream);
}
catch (Throwable ex) {
throw new SerializationFailedException("Failed to deserialize payload. " +
"Is the byte array a result of corresponding serialization for " +
this.deserializer.getClass().getSimpleName() + "?", ex);
}
}

可见DeserializingConverter使用了DefaultDeserializer作为反序列化工具,调用了他的deserialize方法:

1
2
3
4
5
6
7
8
9
10
11
@Override
@SuppressWarnings("resource")
public Object deserialize(InputStream inputStream) throws IOException {
ObjectInputStream objectInputStream = new ConfigurableObjectInputStream(inputStream, this.classLoader);
try {
return objectInputStream.readObject();
}
catch (ClassNotFoundException ex) {
throw new NestedIOException("Failed to deserialize object type", ex);
}
}

对比SerializingConverterDeserializingConverter使用的是ConfigurableObjectInputStream,并调用他的readObject方法进行反序列化。

这种序列化方式,如果保存信息至redis,用客户端查看时,保存的信息看起来像是在原来的字符前面加了几个字符。

比如:

1
2
3
4
JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer();
StringRedisSerializer stringSerializer = new StringRedisSerializer();
byte[] jdkByteArr = jdkSerializer.serialize("CSDN博客");
byte[] stringByteArr = stringSerializer.serialize("CSDN博客");

这种情况下,得到的byte数组是:

jdkByteArr

{-84,-19,0,5,116,0,10,67,83,68,78,-27,-115,-102,-27,-82,-94}

stringByteArr:

{67,83,68,78,-27,-115,-102,-27,-82,-94}

StringRedisSerializer把字符串本身转化成byte数组,而JdkSerializationRedisSerializer在数组前面加了几个字符,这些字符也会被保存到redis中。

所以,从数据上来说,这两种序列化策略处理的数据是不会共通的,各人管各人的。

四.关于redisTemplate的Operations

使用redisTemplate时,除了调用execute方法并自定义RedisCallback之外,还可以使用redisTemplate提供的几个Operations接口。

redisTemplate中定义了以下几个Operations

1
2
3
4
5
6
7
8
9
10
11
12
@Nullable
private ValueOperations<K, V> valueOps;
@Nullable
private ListOperations<K, V> listOps;
@Nullable
private SetOperations<K, V> setOps;
@Nullable
private ZSetOperations<K, V> zSetOps;
@Nullable
private GeoOperations<K, V> geoOps;
@Nullable
private HyperLogLogOperations<K, V> hllOps;

这几个Operations接口,分别提供了对不同种类数据的操作方法。

ValueOperations为例,他提供的方法有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void set(K var1, V var2);

void set(K var1, V var2, long var3, TimeUnit var5);

@Nullable
Boolean setIfAbsent(K var1, V var2);

void multiSet(Map<? extends K, ? extends V> var1);

@Nullable
Boolean multiSetIfAbsent(Map<? extends K, ? extends V> var1);

@Nullable
V get(Object var1);

@Nullable
V getAndSet(K var1, V var2);

@Nullable
List<V> multiGet(Collection<K> var1);

@Nullable
Long increment(K var1, long var2);

@Nullable
Double increment(K var1, double var2);

@Nullable
Integer append(K var1, String var2);

@Nullable
String get(K var1, long var2, long var4);

void set(K var1, V var2, long var3);

@Nullable
Long size(K var1);

@Nullable
Boolean setBit(K var1, long var2, boolean var4);

@Nullable
Boolean getBit(K var1, long var2);

其他的Operations提供的方法各有不同,但是这些Operations的使用方式都是相同的。

不同的Operations分别通过RedisTemplate的以下方法获取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public ValueOperations<K, V> opsForValue() {
if (this.valueOps == null) {
this.valueOps = new DefaultValueOperations(this);
}

return this.valueOps;
}

public ListOperations<K, V> opsForList() {
if (this.listOps == null) {
this.listOps = new DefaultListOperations(this);
}

return this.listOps;
}

public SetOperations<K, V> opsForSet() {
if (this.setOps == null) {
this.setOps = new DefaultSetOperations(this);
}

return this.setOps;
}

public ZSetOperations<K, V> opsForZSet() {
if (this.zSetOps == null) {
this.zSetOps = new DefaultZSetOperations(this);
}

return this.zSetOps;
}

public GeoOperations<K, V> opsForGeo() {
if (this.geoOps == null) {
this.geoOps = new DefaultGeoOperations(this);
}

return this.geoOps;
}

可见,在这些获得Operations的方法中,都提供了一个默认实现类,并且把RedisTemplate对象本身当做参数传给了这个实现类。

还是以ValueOperations为例,RedisTemplate提供的默认实现类是DefaultValueOperations,看看这个类的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
package org.springframework.data.redis.core;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.AbstractOperations.ValueDeserializingRedisCallback;

class DefaultValueOperations<K, V> extends AbstractOperations<K, V> implements ValueOperations<K, V> {
DefaultValueOperations(RedisTemplate<K, V> template) {
super(template);
}

public V get(Object key) {
return this.execute(new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key) {
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
return connection.get(rawKey);
}
}, true);
}

public V getAndSet(K key, V newValue) {
final byte[] rawValue = this.rawValue(newValue);
return this.execute(new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key) {
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
return connection.getSet(rawKey, rawValue);
}
}, true);
}

public Long increment(K key, long delta) {
byte[] rawKey = this.rawKey(key);
return (Long)this.execute((connection) -> {
return connection.incrBy(rawKey, delta);
}, true);
}

public Double increment(K key, double delta) {
byte[] rawKey = this.rawKey(key);
return (Double)this.execute((connection) -> {
return connection.incrBy(rawKey, delta);
}, true);
}

public Integer append(K key, String value) {
byte[] rawKey = this.rawKey(key);
byte[] rawString = this.rawString(value);
return (Integer)this.execute((connection) -> {
Long result = connection.append(rawKey, rawString);
return result != null ? result.intValue() : null;
}, true);
}

public String get(K key, long start, long end) {
byte[] rawKey = this.rawKey(key);
byte[] rawReturn = (byte[])this.execute((connection) -> {
return connection.getRange(rawKey, start, end);
}, true);
return this.deserializeString(rawReturn);
}

public List<V> multiGet(Collection<K> keys) {
if (keys.isEmpty()) {
return Collections.emptyList();
} else {
byte[][] rawKeys = new byte[keys.size()][];
int counter = 0;

Object hashKey;
for(Iterator var4 = keys.iterator(); var4.hasNext(); rawKeys[counter++] = this.rawKey(hashKey)) {
hashKey = var4.next();
}

List<byte[]> rawValues = (List)this.execute((connection) -> {
return connection.mGet(rawKeys);
}, true);
return this.deserializeValues(rawValues);
}
}

public void multiSet(Map<? extends K, ? extends V> m) {
if (!m.isEmpty()) {
Map<byte[], byte[]> rawKeys = new LinkedHashMap(m.size());
Iterator var3 = m.entrySet().iterator();

while(var3.hasNext()) {
Entry<? extends K, ? extends V> entry = (Entry)var3.next();
rawKeys.put(this.rawKey(entry.getKey()), this.rawValue(entry.getValue()));
}

this.execute((connection) -> {
connection.mSet(rawKeys);
return null;
}, true);
}
}

public Boolean multiSetIfAbsent(Map<? extends K, ? extends V> m) {
if (m.isEmpty()) {
return true;
} else {
Map<byte[], byte[]> rawKeys = new LinkedHashMap(m.size());
Iterator var3 = m.entrySet().iterator();

while(var3.hasNext()) {
Entry<? extends K, ? extends V> entry = (Entry)var3.next();
rawKeys.put(this.rawKey(entry.getKey()), this.rawValue(entry.getValue()));
}

return (Boolean)this.execute((connection) -> {
return connection.mSetNX(rawKeys);
}, true);
}
}

public void set(K key, V value) {
final byte[] rawValue = this.rawValue(value);
this.execute(new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key) {
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
connection.set(rawKey, rawValue);
return null;
}
}, true);
}

public void set(K key, V value, final long timeout, final TimeUnit unit) {
final byte[] rawKey = this.rawKey(key);
final byte[] rawValue = this.rawValue(value);
this.execute(new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection) throws DataAccessException {
this.potentiallyUsePsetEx(connection);
return null;
}

public void potentiallyUsePsetEx(RedisConnection connection) {
if (!TimeUnit.MILLISECONDS.equals(unit) || !this.failsafeInvokePsetEx(connection)) {
connection.setEx(rawKey, TimeoutUtils.toSeconds(timeout, unit), rawValue);
}

}

private boolean failsafeInvokePsetEx(RedisConnection connection) {
boolean failed = false;

try {
connection.pSetEx(rawKey, timeout, rawValue);
} catch (UnsupportedOperationException var4) {
failed = true;
}

return !failed;
}
}, true);
}

public Boolean setIfAbsent(K key, V value) {
byte[] rawKey = this.rawKey(key);
byte[] rawValue = this.rawValue(value);
return (Boolean)this.execute((connection) -> {
return connection.setNX(rawKey, rawValue);
}, true);
}

public void set(K key, V value, long offset) {
byte[] rawKey = this.rawKey(key);
byte[] rawValue = this.rawValue(value);
this.execute((connection) -> {
connection.setRange(rawKey, rawValue, offset);
return null;
}, true);
}

public Long size(K key) {
byte[] rawKey = this.rawKey(key);
return (Long)this.execute((connection) -> {
return connection.strLen(rawKey);
}, true);
}

public Boolean setBit(K key, long offset, boolean value) {
byte[] rawKey = this.rawKey(key);
return (Boolean)this.execute((connection) -> {
return connection.setBit(rawKey, offset, value);
}, true);
}

public Boolean getBit(K key, long offset) {
byte[] rawKey = this.rawKey(key);
return (Boolean)this.execute((connection) -> {
return connection.getBit(rawKey, offset);
}, true);
}
}

所有Operations实现类都是AbstractOperations的子类,另外各自实现各自的接口。

实现类的方法中多数都是调用了this.execute()方法,这个方法在父类AbstractOperations中,最终调用的其实也是RedisTemplateexecute()方法。

以上面DefaultValueOperationsset()方法为例,看一下代码:

1
2
3
4
5
6
7
8
9
public void set(K key, V value) {
final byte[] rawValue = this.rawValue(value);
this.execute(new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key) {
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
connection.set(rawKey, rawValue);
return null;
}
}, true);
}

首先是对value的处理,调用this.rawValue()方法,把value序列化成byte数组,这个方法在父类AbstractOperations中:

1
2
3
byte[] rawValue(Object value) {
return this.valueSerializer() == null && value instanceof byte[] ? (byte[])((byte[])value) : this.valueSerializer().serialize(value);
}

可见,代码用的是自己的valueSerializer来序列化value,这个valueSerializer来自RedisTemplate

回到set()方法,value序列化完成后,调用this.execute()方法,给此方法传递的第一个参数是:

1
2
3
4
5
6
new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key) {
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
connection.set(rawKey, rawValue);
return null;
}
}

这个参数实际上是一个ValueDeserializingRedisCallback对象,在其中定义了inRedis()方法的实现。

this.execute()方法在父类AbstractOperations中:

1
2
3
4
@Nullable
<T> T execute(RedisCallback<T> callback, boolean b) {
return this.template.execute(callback, b);
}

其中this.template指的就是初始化时传入的RedisTemplate,其execute()方法是这样的:

1
2
3
4
@Nullable
public <T> T execute(RedisCallback<T> action, boolean exposeConnection) {
return this.execute(action, exposeConnection, false);
}

然后调用下面的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Nullable
public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {
Assert.isTrue(this.initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(action, "Callback object must not be null");
RedisConnectionFactory factory = this.getRequiredConnectionFactory();
RedisConnection conn = null;

Object var11;
try {
if (this.enableTransactionSupport) {
conn = RedisConnectionUtils.bindConnection(factory, this.enableTransactionSupport);
} else {
conn = RedisConnectionUtils.getConnection(factory);
}

boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);
RedisConnection connToUse = this.preProcessConnection(conn, existingConnection);
boolean pipelineStatus = connToUse.isPipelined();
if (pipeline && !pipelineStatus) {
connToUse.openPipeline();
}

RedisConnection connToExpose = exposeConnection ? connToUse : this.createRedisConnectionProxy(connToUse);
T result = action.doInRedis(connToExpose);
if (pipeline && !pipelineStatus) {
connToUse.closePipeline();
}

var11 = this.postProcessResult(result, connToUse, existingConnection);
} finally {
RedisConnectionUtils.releaseConnection(conn, factory);
}

return var11;
}

方法初始化了RedisConnection,最后面调用了RedisCallbackdoInRedis()方法,也就是这一行:

1
T result = action.doInRedis(connToExpose);

这里的变量action就是在set()方法中自定义的new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key)

ValueDeserializingRedisCallback类是AbstractOperations的内部抽象类,他的doInRedis()方法是这样的:

1
2
3
4
public final V doInRedis(RedisConnection connection) {
byte[] result = this.inRedis(AbstractOperations.this.rawKey(this.key), connection);
return AbstractOperations.this.deserializeValue(result);
}

可见调用了inRedis()方法,其第一个参数是序列化后的key,调用的是AbstractOperationsrawKey()方法,代码如下:

1
2
3
4
byte[] rawKey(Object key) {
Assert.notNull(key, "non null key required");
return this.keySerializer() == null && key instanceof byte[] ? (byte[])((byte[])key) : this.keySerializer().serialize(key);
}

这里把key进行序列化,keySerializer()方法从RedisTemplate中获取keySerializer,并由keySerializerkey进行序列化。

ValueDeserializingRedisCallback类中的inRedis()方法是抽象方法,具体的实现在DefaultValueOperationsset()方法中,也就是这一部分:

1
2
3
4
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
connection.set(rawKey, rawValue);
return null;
}

最终调用的是RedisConnectionset()方法,完成Redisset操作。

以上就是在RedisTemplate中使用ValueOperations进行set操作的全部代码流程。

Redis的不同操作分散在RedisTemplate的不同Operations中,只是调用的方法不同,调用流程都差不多。

参考地址

如果大家喜欢我的文章,可以关注个人订阅号。欢迎随时留言、交流。如果想加入微信群的话一起讨论的话,请加管理员微信号:chengcheng222e,他会拉你们进群。

简栈文化服务订阅号