自动装配
以spring-boot-starter-data-redis
的2.6.11
版本为例子,在spring-boot-autoconfigure
中的spring.factoires
有引入RedisAutoConfiguration
RedisAutoConfiguration
RedisAutoConfiguration
会根据条件判断是否需要加载redisTemplate
,有两个RedisTemplate
,一个是默认的,一个是字符串序列化化的。
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
public RedisAutoConfiguration() {
}
@Bean
@ConditionalOnMissingBean(
name = {"redisTemplate"}
)
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
return new StringRedisTemplate(redisConnectionFactory);
}
}
RedisTemplate
RedisTemplate
实现了InitializingBean
接口,在系统启动的时候,会重写afterPropertiesSet
方法,核心就是设置序列化器。默认的序列化器是JdkSerializationRedisSerializer
。
public void afterPropertiesSet() {
super.afterPropertiesSet();
boolean defaultUsed = false;
if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
if (enableDefaultSerializer) {
if (keySerializer == null) {
keySerializer = defaultSerializer;
defaultUsed = true;
}
if (valueSerializer == null) {
valueSerializer = defaultSerializer;
defaultUsed = true;
}
if (hashKeySerializer == null) {
hashKeySerializer = defaultSerializer;
defaultUsed = true;
}
if (hashValueSerializer == null) {
hashValueSerializer = defaultSerializer;
defaultUsed = true;
}
}
if (enableDefaultSerializer && defaultUsed) {
Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized");
}
if (scriptExecutor == null) {
this.scriptExecutor = new DefaultScriptExecutor<>(this);
}
initialized = true;
}
StringRedisTemplate
StringRedisTemplate
指定序列化器,new StringRedisSerializer(StandardCharsets.UTF_8)
。
public StringRedisTemplate() {
setKeySerializer(RedisSerializer.string());
setValueSerializer(RedisSerializer.string());
setHashKeySerializer(RedisSerializer.string());
setHashValueSerializer(RedisSerializer.string());
}
序列化器
JdkSerializationRedisSerializer
生成字节数组,SerializingConverter#convert-->Serializer#serializeToByteArray
default byte[] serializeToByteArray(T object) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
this.serialize(object, out);
return out.toByteArray();
}
反序列化,DeserializingConverter#convert-->DefaultDeserializer#deserialize
。
public Object deserialize(InputStream inputStream) throws IOException {
ConfigurableObjectInputStream objectInputStream = new ConfigurableObjectInputStream(inputStream, this.classLoader);
try {
return objectInputStream.readObject();
} catch (ClassNotFoundException var4) {
throw new NestedIOException("Failed to deserialize object type", var4);
}
}
StringRedisSerializer
@Override
public String deserialize(@Nullable byte[] bytes) {
return (bytes == null ? null : new String(bytes, charset));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.serializer.RedisSerializer#serialize(java.lang.Object)
*/
@Override
public byte[] serialize(@Nullable String string) {
return (string == null ? null : string.getBytes(charset));
}
案例:
JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
byte[] bytes = jdkSerializationRedisSerializer.serialize("abc");
Object res = jdkSerializationRedisSerializer.deserialize(bytes);
System.out.println(new String(bytes) + "," + res);
RedisSerializer<String> stringRedisSerializer = RedisSerializer.string();
byte[] strBytes = stringRedisSerializer.serialize("abc");
Object strRes = stringRedisSerializer.deserialize(strBytes);
System.out.println(new String(strBytes) + "," + strRes);
RedisTemplate
获取数据
使用方法
@Autowired
private RedisTemplate redisTemplate;
@GetMapping("operate")
public void operate() {
redisTemplate.opsForValue().set("ccc", "111");
redisTemplate.opsForValue().get("ccc")
}
DefaultValueOperations#get(java.lang.Object)
@Override
public V get(Object key) {
return execute(new ValueDeserializingRedisCallback(key) {
@Override
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
return connection.get(rawKey);
}
});
}
AbstractOperations#execute
,使用template执行回调函数。
@Nullable
<T> T execute(RedisCallback<T> callback) {
return template.execute(callback, true);
}
RedisTemplate#execute()
,获取连接,执行回调函数。
@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);
}
}
ValueDeserializingRedisCallback#doInRedis
,根据key进行序列化,获取到的value进行反序列化。
public final V doInRedis(RedisConnection connection) {
byte[] result = inRedis(rawKey(key), connection);
return deserializeValue(result);
}
byte[] rawKey(Object key) {
Assert.notNull(key, "non null key required");
if (keySerializer() == null && key instanceof byte[]) {
return (byte[]) key;
}
return keySerializer().serialize(key);
}
RedisTemplate
存储数据
DefaultValueOperations#set(K, V)
,对value进行序列化
@Override
public void set(K key, V value) {
byte[] rawValue = rawValue(value);
execute(new ValueDeserializingRedisCallback(key) {
@Override
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
connection.set(rawKey, rawValue);
return null;
}
});
}
ValueDeserializingRedisCallback#doInRedis
,将key进行序列化,执行回调方法。
public final V doInRedis(RedisConnection connection) {
byte[] result = inRedis(rawKey(key), connection);
return deserializeValue(result);
}