2.X RedisCacheManager中没有RedisTemplate了,看起来更加复杂了,我们先弄清楚各个成员变量的含义,这样后面看源码的过程就会明了一些。
1. RedisCacheManager
里面的各个对象在2-5中详细解释。
public class RedisCacheManager extends AbstractTransactionSupportingCacheManager {
// cacheWriter,实际对Redis进行读写,键值都是byte[]。
private final RedisCacheWriter cacheWriter;
// 默认的配置,包括ttl,序列化方式等。
private final RedisCacheConfiguration defaultCacheConfig;
// 所有预先定义好的Cache各自对应的配置(不预先定义好就等用到了再创建)。
private final Map<String, RedisCacheConfiguration> initialCacheConfiguration;
// 当Cache不存在时能否创建。
private final boolean allowInFlightCacheCreation;
}
2. RedisCacheWriter
主要方法如下,可以看出就是跟RedisTemplate差不多的东西,但是只能操作byte[]。序列化和反序列化操作是在其它地方完成的,这个后面会说。
public interface RedisCacheWriter {
void put(String name, byte[] key, byte[] value, @Nullable Duration ttl);
byte[] get(String name, byte[] key);
byte[] putIfAbsent(String name, byte[] key, byte[] value, @Nullable Duration ttl);
void remove(String name, byte[] key);
void clean(String name, byte[] pattern);
}
3. RedisCacheConfiguration
public class RedisCacheConfiguration {
// 这四个是RedisCache的常规配置,就对应于CacheProperties.Redis中的那四个配置。
private final Duration ttl;
private final boolean cacheNullValues;
private final CacheKeyPrefix keyPrefix;
private final boolean usePrefix;
// 这两个东西完成了序列化操作,每个Pair里面存了一个Reader和一个Writer,具体见4
private final SerializationPair<String> keySerializationPair;
private final SerializationPair<Object> valueSerializationPair;
// 把object转成String,用于键的转换。
private final ConversionService conversionService;
}
CacheProperties.Redis
@ConfigurationProperties(prefix = "spring.cache")
public class CacheProperties {
public static class Redis {
private Duration timeToLive;
private boolean cacheNullValues = true;
private String keyPrefix;
private boolean useKeyPrefix = true;
}
}
4. SerializationPair
它是RedisSerializationContext中的一个子接口,代码比较长,就看下面这一段。
interface SerializationPair<T> {
static <T> SerializationPair<T> fromSerializer(RedisSerializer<T> serializer) {
// serializer是序列化器,比如json序列化
Assert.notNull(serializer, "RedisSerializer must not be null!");
//RedisSerializerToSerializationPairAdapter的实现在下面
return new RedisSerializerToSerializationPairAdapter<>(serializer);
}
}
// # class RedisSerializerToSerializationPairAdapter<T>
protected RedisSerializerToSerializationPairAdapter(@Nullable RedisSerializer<T> serializer) {
//看名字就能知道,这里创建了一个Reader,一个Writer,然后组成了一个pair 。读写过程中用的
//序列化器就是传入的serializer。
pair = new DefaultSerializationPair(new DefaultRedisElementReader<>(serializer),
new DefaultRedisElementWriter<>(serializer));
}
// SerializationPair的实现,可以看到它就是由reader,writer组成的。
class DefaultSerializationPair<T> implements SerializationPair<T> {
private final RedisElementReader<T> reader;
private final RedisElementWriter<T> writer;
}
// RedisElementReader的实现,这里真正调用了serializer序列化操作。
// RedisElementWriter也差不多,只不过把read改成write。
class DefaultRedisElementReader<T> implements RedisElementReader<T> {
private final @Nullable RedisSerializer<T> serializer;
public T read(ByteBuffer buffer) {
if (serializer == null) {
return (T) buffer;
}
return serializer.deserialize(ByteUtils.extractBytes(buffer));
}
}
5. RedisCache
CacheManager是管理Cache的,Cache才是实际进行读写的地方,看代码前可以想一下,读写过程中需要一个RedisCacheWriter,序列化器,string转换器,ttl等配置。这些东西CacheManager都已经准备好了。
public class RedisCache extends AbstractValueAdaptingCache {
// Cache名
private final String name;
// 同CacheManager
private final RedisCacheWriter cacheWriter;
// 对应于这个Cache的配置,功能就是3,4中说的。
private final RedisCacheConfiguration cacheConfig;
// RedisCacheConfiguration中的conversionService。单独提取出来了而已。
private final ConversionService conversionService;
6. 默认RedisManager创建的过程
- CacheAutoConfiguration通过CacheConfigurationImportSelector导入所有的ConfigurationClass。
Map<CacheType, Class<?>> mappings = new EnumMap<>(CacheType.class);
mappings.put(CacheType.GENERIC, GenericCacheConfiguration.class);
mappings.put(CacheType.EHCACHE, EhCacheCacheConfiguration.class);
mappings.put(CacheType.HAZELCAST, HazelcastCacheConfiguration.class);
mappings.put(CacheType.INFINISPAN, InfinispanCacheConfiguration.class);
mappings.put(CacheType.JCACHE, JCacheCacheConfiguration.class);
mappings.put(CacheType.COUCHBASE, CouchbaseCacheConfiguration.class);
mappings.put(CacheType.REDIS, RedisCacheConfiguration.class);
mappings.put(CacheType.CAFFEINE, CaffeineCacheConfiguration.class);
mappings.put(CacheType.SIMPLE, SimpleCacheConfiguration.class);
mappings.put(CacheType.NONE, NoOpCacheConfiguration.class);
- 它是按从上到下的顺序来检索的,如果前面的创建成功了就不会创建后面的了。我们具体看RedisCacheConfiguration.class。
- 进入到RedisCacheConfiguration.class里面,下面的代码都注释了。
@Configuration
@ConditionalOnClass(RedisConnectionFactory.class)
@AutoConfigureAfter(RedisAutoConfiguration.class)
@ConditionalOnBean(RedisConnectionFactory.class)
@ConditionalOnMissingBean(CacheManager.class)
@Conditional(CacheCondition.class)
class RedisCacheConfiguration {
// 缓存的配置信息,就是yaml中spring.cache开头的。具体到redis就是那四个。
private final CacheProperties cacheProperties;
// 定制化,这里其实没有用到。因为一个Customizer都没有。
private final CacheManagerCustomizers customizerInvoker;
// 解释在上面的3,4中,
private final org.springframework.data.redis.cache.RedisCacheConfiguration redisCacheConfiguration;
RedisCacheConfiguration(CacheProperties cacheProperties,
CacheManagerCustomizers customizerInvoker,
ObjectProvider<org.springframework.data.redis.cache.RedisCacheConfiguration> redisCacheConfiguration) {
this.cacheProperties = cacheProperties;
this.customizerInvoker = customizerInvoker;
// redisCacheConfiguration.getIfAvailable()结果是null,具体的配置在最后那个determineConfiguration中。
this.redisCacheConfiguration = redisCacheConfiguration.getIfAvailable();
}
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory,
ResourceLoader resourceLoader) {
// redisConnectionFactory是Redis处理连接,是Redis自己配置的。
// builder是RedisCacheManager的构造器。
RedisCacheManagerBuilder builder = RedisCacheManager
// 配置连接信息
.builder(redisConnectionFactory)
// 配置 CacheManager中的defaultCacheConfig
.cacheDefaults(determineConfiguration(resourceLoader.getClassLoader()));
// 预先定义好的缓存名们,这些缓存会在CacheManger创建好后就创建出来,否则第一次要用到了才创建。
List<String> cacheNames = this.cacheProperties.getCacheNames();
if (!cacheNames.isEmpty()) {
builder.initialCacheNames(new LinkedHashSet<>(cacheNames));
}
// 加入定制信息,这里实际没作用,相当于直接返回builder.build()。
return this.customizerInvoker.customize(builder.build());
}
private org.springframework.data.redis.cache.RedisCacheConfiguration determineConfiguration(
ClassLoader classLoader) {
if (this.redisCacheConfiguration != null) {
return this.redisCacheConfiguration;
}
// 获取redis相关的配置,ttl等4个配置信息。
Redis redisProperties = this.cacheProperties.getRedis();
// 获取默认的RedisCacheConfiguration。
org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration
.defaultCacheConfig();
// 设置序列化器。
config = config.serializeValuesWith(SerializationPair
.fromSerializer(new JdkSerializationRedisSerializer(classLoader)));
// 后面就是设置redis相关的配置,ttl等4个配置信息
if (redisProperties.getTimeToLive() != null) {
config = config.entryTtl(redisProperties.getTimeToLive());
}
if (redisProperties.getKeyPrefix() != null) {
config = config.prefixKeysWith(redisProperties.getKeyPrefix());
}
if (!redisProperties.isCacheNullValues()) {
config = config.disableCachingNullValues();
}
if (!redisProperties.isUseKeyPrefix()) {
config = config.disableKeyPrefix();
}
return config;
}
}
- 现在RedisManager就生成了,接下去要创建预先定义好的那些Cache,这一步是通过Spring的afterPropertiesSet实现的。
public abstract class AbstractCacheManager implements CacheManager, InitializingBean {
private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<>(16);
private volatile Set<String> cacheNames = Collections.emptySet();
// 这里去初始化预先定义好的Cache
public void afterPropertiesSet() {
initializeCaches();
}
public void initializeCaches() {
// 调用抽象函数loadCaches。
Collection<? extends Cache> caches = loadCaches();
synchronized (this.cacheMap) {
this.cacheNames = Collections.emptySet();
this.cacheMap.clear();
Set<String> cacheNames = new LinkedHashSet<>(caches.size());
for (Cache cache : caches) {
String name = cache.getName();
this.cacheMap.put(name, decorateCache(cache));
cacheNames.add(name);
}
this.cacheNames = Collections.unmodifiableSet(cacheNames);
}
}
// 由RedisCacheManager具体实现。
protected abstract Collection<? extends Cache> loadCaches();
}
// # RedisCacheManger
protected Collection<RedisCache> loadCaches() {
List<RedisCache> caches = new LinkedList<>();
for (Map.Entry<String, RedisCacheConfiguration> entry : initialCacheConfiguration.entrySet()) {
caches.add(createRedisCache(entry.getKey(), entry.getValue()));
}
return caches;
}
7. 总结
RedisManager为RedisCache准备了RedisCacheWriter 和 RedisCacheConfiguration ,RedisCacheWriter完成了读写byte[],RedisCacheConfiguration中的SerializationPair完成了byte和object之间的转换,还存了Redis缓存用到的ttl等四个配置信息。