• 2CacheSpringRedisAutoConfiguration配置文件在RedisAutoConfiguration之后,J2CacheAutoConfiguration之前加载。
  • 通过j2cache.redis-client可以配置redis客户端:Jedis或则Lettuce,本次学习使用Lettuce。
  • 使用RedisStandaloneConfiguration构建LettuceConnectionFactory对象。
  • 最后将RedisTemplate的对象交给Spring管理。
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
@Bean("j2CacheRedisTemplate")
public RedisTemplate<String, Serializable> j2CacheRedisTemplate(
@Qualifier("j2CahceRedisConnectionFactory") RedisConnectionFactory j2CahceRedisConnectionFactory,
@Qualifier("j2CacheValueSerializer") RedisSerializer<Object> j2CacheSerializer) {
RedisTemplate<String, Serializable> template = new RedisTemplate<String, Serializable>();
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setDefaultSerializer(j2CacheSerializer);
template.setConnectionFactory(j2CahceRedisConnectionFactory);
return template;
}
//j2CahceRedisConnectionFactory为:LettuceConnectionFactory
//j2CacheSerializer为:J2CacheSerializer,底层使用net.oschina.j2cache.util.SerializationUtils#g_serializer
@Primary
@Bean("j2CahceRedisConnectionFactory")
public LettuceConnectionFactory lettuceConnectionFactory(net.oschina.j2cache.J2CacheConfig j2CacheConfig) {
//简化了一下
LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder config = LettucePoolingClientConfiguration.builder();
config.commandTimeout(Duration.ofMillis(5000));
config.poolConfig(getGenericRedisPool());
RedisStandaloneConfiguration single = new RedisStandaloneConfiguration("xxxx", 6379);
single.setDatabase(10);
single.setPassword("****");
LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(single, config.build());
return connectionFactory;
}

再看RedisTemplate类:
img

RedisTemplate继承了RedisAccessor类,实现RedisOperations和BeanClassLoaderAware接口,其中RedisAccessor维护了redis连接工厂,RedisOperations定义redis相关操作。

这里的connectionFactory为LettuceConnectionFactory:操作Redis的准备工作

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
private @Nullable AbstractRedisClient client;
private @Nullable LettuceConnectionProvider connectionProvider;
private @Nullable LettuceConnectionProvider reactiveConnectionProvider;

public void afterPropertiesSet() {
//获取RedisClient客户端
this.client = createClient();
//org.springframework.data.redis.connection.lettuce.LettuceConnection#CODEC
//ByteArrayCodec
this.connectionProvider = new ExceptionTranslatingConnectionProvider(createConnectionProvider(client, CODEC));

//org.springframework.data.redis.connection.lettuce.LettuceReactiveRedisConnection#CODEC
//ByteBufferCodec
this.reactiveConnectionProvider = new ExceptionTranslatingConnectionProvider(
createConnectionProvider(client, LettuceReactiveRedisConnection.CODEC));

//略
}
protected AbstractRedisClient createClient() {
//略
RedisURI uri = isDomainSocketAware()
? createRedisSocketURIAndApplySettings(((DomainSocketConfiguration) configuration).getSocket())
: createRedisURIAndApplySettings(getHostName(), getPort());

//clientConfiguration为:DefaultLettucePoolingClientConfiguration
RedisClient redisClient = clientConfiguration.getClientResources() //
.map(clientResources -> RedisClient.create(clientResources, uri)) //
.orElseGet(() -> RedisClient.create(uri));
clientConfiguration.getClientOptions().ifPresent(redisClient::setOptions);

return redisClient;
}
  • 首先创建RedisClient客户端

  • 之后创建LettuceConnectionProvider,这里使用了装饰器模式:StandaloneConnectionProvider->LettucePoolingConnectionProvider->ExceptionTranslatingConnectionProvider,从名称上也能大概看出装-

    • StandaloneConnectionProvider:独立的获取redis连接,底层使用Netty框架。
  • LettucePoolingConnectionProvider:redis连接池化技术,使用org.apache.commons.pool2.impl.GenericObjectPool

  • ExceptionTranslatingConnectionProvider:Redis连接异常转换。