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注解。

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值