Springboot的redisTemplate究竟用的是哪个bean

在自动装配一个RedisTemplate对象时,我时常有疑惑用到的究竟是spring自带的还是我们自定义的。

不定义自定义bean时
@Autowired
private RedisTemplate redisTemplate;

上面的redisTemplate实际上是RedisAutoConfiguration类中通过redisTempate这个bean自动装载的。

@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) {
	StringRedisTemplate template = new StringRedisTemplate();
	template.setConnectionFactory(redisConnectionFactory);
	return template;
}

由于该类中还定义了stringRedisTemplate的bean,所以下面的自动装配得到的就是该bean

@Autowired
private RedisTemplate stringRedisTemplate;

注意:句柄必须是stringRedisTemplate,这个句柄对应的是bean的名字。

但是只是通过句柄来确定用的是哪个bean,未免有点不太严谨,因为在我有限的认知中,句柄只是句柄而已,改成其他字符串它还是一个句柄。但是你会发现改了句柄之后就会报错了。

有两种方式可以解决:

1,使用@Qualifier注解

2,将RedisTemplate泛型定义完整,此时句柄可以随便修改

@Autowired
private RedisTemplate<String, String> whichRedisTemplate;

可以得出结论:究竟用的是哪个bean,可以由下面3步来确定

1,@Qualifer注解中标明的bean名字

2,定义的泛型

3,句柄名字

注意:上面3步是由优先顺序的。

如果有好奇下面的定义是用的哪个bean的,可以直接给出答案,是RedisAutoConfiguration类中的redisTempate。

@Autowired
private RedisTemplate<Object,Object> stringRedisTemplate;

有定义自定义bean时

首先我们是不能定义相同的bean名字的。因为已经有了RedisAutoConfiguration类中定义的两个bean,也就是说我们不能再定义名称为redisTemplate或stringRedisTemplate的bean,不然会抛出BeanDefinitionOverrideException

有自定义bean时确定用到的时哪个bean的方法还是前面3步。值得注意的是第2和第3步的定义是可能会产生歧义的。现在自定义下面的bean,注意bean名字和valueSerializer和spring定义的stringRedisTemplate是不一样的

@Bean
public RedisTemplate<String, String> stringRedisTemplate_1(LettuceConnectionFactory connectionFactory) {
    RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Map.class));
    redisTemplate.setConnectionFactory(connectionFactory);
    return redisTemplate;
}

那么下面的定义是用的哪个对象呢

@Autowired
private RedisTemplate<String,String> stringRedisTemplate;

答案是spring自定的stringRedisTemplate,那么如果将上面的句柄改成stringRedisTemplate_2,结果就是会报错,因为spring无法确定,所以会抛出NoUniqueBeanDefinitionException。

也就是说想要确定我们定义的自动装载对象就是我们想要的对象时,最好是泛型和句柄都和定义bean时保持一致。

以上都是废话,总结一句话:实际使用中,最好使用@Qualifier注解。

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-01-12 06:12:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-12 06:12:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-12 06:12:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-12 06:12:01       20 阅读

热门阅读

  1. 数据结构-树(C++)

    2024-01-12 06:12:01       39 阅读
  2. Wargames与bash知识14

    2024-01-12 06:12:01       40 阅读
  3. Spark: 检查数据倾斜的方法以及解决方法总结

    2024-01-12 06:12:01       31 阅读
  4. 探索计算机网络:应用层的魅力

    2024-01-12 06:12:01       39 阅读
  5. Linux 命令解释程序(shell)的模拟实现

    2024-01-12 06:12:01       32 阅读
  6. 初识C#语言

    2024-01-12 06:12:01       36 阅读