- 为什么要自定义RedisCacheManager
CacheManager是对Cache进行管理,创建,获取,销毁等操作的,在创建Cache时,需要对其序列化,如下
public static RedisCacheConfiguration defaultCacheConfig(@Nullable ClassLoader classLoader) {
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
registerDefaultConverters(conversionService);
return new RedisCacheConfiguration(Duration.ZERO, true, true, CacheKeyPrefix.simple(),
SerializationPair.fromSerializer(RedisSerializer.string()),
SerializationPair.fromSerializer(RedisSerializer.java(classLoader)), conversionService);
}
可以看到对value的序列化是SerializationPair.fromSerializer(RedisSerializer.java(classLoader)),我们继续追看RedisSerializer.java(classLoader)的返回值:
static RedisSerializer
默认使用的是JDK的序列化机制,这就使得,我们存入redis中的数据类似于下面这样:
127.0.0.1:6379> get "emp::10001" "xacxedx00x05srx00x1acom.nl.cache.bean.Employeex1fx10x81"xbdxdcx8cx9cx02x00x05Lx00x03dIdtx00x13Ljava/lang/Integer;Lx00x05emailtx00x12Ljava/lang/String;Lx00x06genderqx00~x00x01Lx00x02idqx00~x00x01Lx00blastNameqx00~x00x02xpptx00x0echo@unkown.comsrx00x11java.lang.Integerx12xe2xa0xa4xf7x81x878x02x00x01Ix00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00x00x01sqx00~x00x05x00x00'x11tx00x03cho"
这让我们在存入数据后,想要比对时,不容易查看。所以我们决定,让以json的形式进行序列化。
- 自定义CacheManager
-注:springboot版本2.5.6
我们参照org.springframework.data.redis.cache.RedisCacheManager的create()方法
public static RedisCacheManager create(RedisConnectionFactory connectionFactory) {
Assert.notNull(connectionFactory, "ConnectionFactory must not be null!");
return new RedisCacheManager(new DefaultRedisCacheWriter(connectionFactory),
RedisCacheConfiguration.defaultCacheConfig());
}
我们只需修改RedisCacheManager构造方法的第二个参数RedisCacheConfiguration.defaultCacheConfig(),它的返回值是一个RedisCacheConfiguration类型,自然想到new一个就可以了,但发现它的构造方法是私有的,有两种方法,一种就是仿照这个类,写一个相同的类,把构造方法改为public,另一个就是通过反射的方式,鉴于再写一个类,冗余比较多,就决定用反射。
参考文章开头第一段代码,创建RedisCacheConfiguration
@Bean
public RedisCacheManager customizedCacheManager(RedisConnectionFactory connectionFactory) throws InvocationTargetException, IllegalAccessException, InstantiationException {
//对 对象类型(employee)和string类型的序列化
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Employee.class);
Jackson2JsonRedisSerializer keySerializer = new Jackson2JsonRedisSerializer<>(String.class);
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
RedisCacheConfiguration.registerDefaultConverters(conversionService);
RedisCacheConfiguration redisCacheConfiguration = null;
Constructor[] constructors = RedisCacheConfiguration.class.getDeclaredConstructors();
for (Constructor constructor : constructors) {
constructor.setAccessible(true);
if(constructor.getParameterTypes().length==7){//因为只有构造方法,所以判断方式比较随意
redisCacheConfiguration = (RedisCacheConfiguration) constructor.newInstance(Duration.ZERO, true, true, CacheKeyPrefix.simple(), RedisSerializationContext.SerializationPair.fromSerializer(keySerializer), RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer),conversionService);
}
}
assert redisCacheConfiguration != null;
//通过RedisCacheManagerBuilder来创建RedisCacheManager,也可以直接new
return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(connectionFactory).cacheDefaults(redisCacheConfiguration).build();
}
将该组件注册到spring容器中即可。
这样,我们再次通过后台程序缓存写入redis中时,就可以看到下面的形式:
127.0.0.1:6379> keys *
1) ""emp::10001""
127.0.0.1:6379> get ""emp::10001""
"{"id":10001,"lastName":"cho","email":"cho@unkown.com","gender":1,"dId":null}"



