Redis多数据源 RestTemplate 坑业务新需求需要依赖 Redis额外申请新的Redis实例。 说白了,就是
一、前言
背景:业务新需求需要依赖 Redis,避免影响原先业务,额外申请新的Redis实例。

说白了,就是一个业务服务里创建了 2个 RestTemplate(Redis Client)用于分别访问 Redis。
原先项目里已经配置好一个 RestTemplate 去访问公共的 Redis,当前只需要配置新的 Redis 配置。
起手就是 3个步骤:
- 配置 Redis 连接信息:存储连接信息
- 创建连接配置:ConnectionFactory
- 创建 RedisTemplate

上手直接配置完,开发完业务代码,美滋滋😄💃。
突然,一抖机灵,想到配置新的Redis,会不会影响老的Redis连接 Client,
带这个问题,我写了demo简单测试了下:

发现两个 redisTemplate 连接信息都指向一个 新的Redis:
- 我本地模拟新的 Redis:IP为 localhost; 端口为 6380

啊啊啊啊啊!出现新问题了。
现在解决这个问题,方向可分为:
- 不影响到原先的Redis配置(最优方式)
- 分开配置 2个Redis配置信息(有风险,可能会影响到原先业务:序列化方式等)
二、排查过程:心路历程
初衷就是:不要影响到老的 Redis 配置等环境信息。
- 不要再改别的地方的代码。
(1)遇事不决:问 ChatGPT
ChatGPT给出的答案差不多,步骤也是一样的3步骤,结论就是使用:注解 @Primary
使用 @Primary
,就需要额外配置一份原先的配置,虽然能够解决当下问题,但同时也带来了新问题。
- 问题 1 :Redis 的序列化方式不同的,这要看原先老的配置序列化方式是怎样的。需要保持一致。
- 问题 2:引入新变化,那么引用的地方都要重新回归一遍,通过后才能上线。
显然这不是最优解法,还要改配置,又要回归测试,麻烦的一啊。😭
为了彻底解决这个问题,我们需要探寻源码,找到其中的答案。
(2)刨根问底:为什么会影响到默认的 RestTemplate ?
在分析前,先了解下 SpringBoot 这几个注解:有用。
条件注解 | 作用 | 条件注解解析类 |
---|---|---|
ConditionalOnBean | ApplicationContext 存在某些Bean时条件才成立 | OnBeanCondition |
ConditionalOnClass | classpath 中存在某些Class时条件才成立 | OnClassCondition |
ConditionnalOnMissingBean | ApplicationContext 不存在某些Bean时才成立 | OnBeanCondition |
SpringBoot 中有一个很重要的模块:spring-boot-autoconfigure
- 该模块包含很多第三方依赖
AutoConfiguration
(自动化配置类):KafkaAutoConfiguration、WebMvcAutoConfiguration 等。 - 这些 AutoConfiguration 只会在特定的情况下才会生效,这些特定情况就是条件注解。
1、自动装配过程
Spring Boot 中 RestTemplate 和 Redis 的自动装配是两个独立的过程,但它们都遵循 Spring Boot 的自动配置原则。
- 这里主要分析 Redis 的自动装配过程。
Redis
的自动装配:主要由 RedisAutoConfiguration
类处理。
- 检测到 RedisOperations 接口存在。
- 读取 Redis 相关的配置属性:即
RedisProperties
。 - 根据客户端库选择 Lettuce 或 Jedis 配置。
- 创建 RedisConnectionFactory。
- 创建
RedisTemplate
和StringRedisTemplate
beans。
2、坑
从RedisAutoConfiguration
可以观察到:
- 自动生效配置
RedisProperties
,这里主要读取配置文件中spring.redis
下的配置。 - 注解:
@ConditionnalOnMissingBean
,来创建 RestTemplate - 不存在 Bean 名为
stringRedisTemplate
,会自动创建。
可以从上图看到,创建连接信息可以选择:LettuceConnectionConfiguration
、JedisConnectionConfiguration
但从上图没看到:如何创建Redis连接信息(并尝试连接 Redis)
坑: @ConditionalOnMissingBean(RedisConnectionFactory.class)
- 这个注解表示:只有在当前
Spring
上下文中不存在RedisConnectionFactory
类型的Bean
时,才会创建被该注解修饰的Bean
。 - 所以有第二个配置,原先默认配置就失效了。
这就解释了:为什么配置了新的Redis配置,2个Redis Client 都指向同一份配置。
解决:创建初始化LettuceConnectionFactory
时,不生成对应 Bean,即可。

(3)小结
小结:
- 系统中没有自定义创建:Bean 名称为
restTemplate
,会自动创建默认的restTemplate
- 自动会默认创建
restTemplate
和stringRedisTemplate
两个 Bean - 使用
@Autowired
注入restTemplate
时候,会根据范型类别来选择。
-
- SpringBoot 会默认创建
RedisTemplate
和StringRedisTemplate
beans。 - 默认创建的
RedisTemplate
,实际是RedisTemplate<Object, Object>
- 但如果使用
RedisTemplate<String, Object>
就会报错
- SpringBoot 会默认创建
会报如下错误:
No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>'
available: expected at least 1 bean which qualifies as autowire candidate.
转载自:https://juejin.cn/post/7424908830902255668