springboot原始版本:2.2.4,springboot升级版本:2.6.4
现象:
项目因为业务需要,自定义的redis配置类里,声明了3个redisConnectionFactory,3个redistemplate,且命名不是“redistemplate“、和“stringRedisTemplate“。
service实现类里注入了redisTemplate、stringRedisTemplate。
之前的版本,是可以成功注入并运行的,升级版本后,运行项目,报错:
看到此类报错,直接在自定义的redis配置文件里声明了一个stringRedisTemplate,即可暴力解决,但是思考下,之前版本可以,为什么现在的版本,不行了呢?
而springboot可以自动配置redisTemplate的,按理说就算不在配置中心配置,也可以成功引入redisTemplate。说到这里,我们看下springboot是如何自动配置redisTemplate的(参考:redistemplate是如何在springboot中自动配置的_且行且珍惜、的博客-CSDN博客_"@bean(name = \"redistemplate\")"),首先要找到它的自动配置类,在spring-boot-autoconfigure.jar 下的spring.factories,搜索下redis可以找到具体的默认配置bean。
进入到RedisAutoConfiguration查看他的源码
项目用debug方式运行,查看自动配置情况,发现stringRedisTemplate并没有自动配置成功,因为redisFactory有多个,没有指定首选:
然后在redis自定义配置文件里,将一个redisFactory指定为首选,运行项目就可以成功了。
还是那个老问题,之前版本没有指定首选,怎么就可以成功呢,所以就比对了两个版本的redisTemplate自动配置类,旧版本如下:
新版本如下:
发现,新版本多了一个注解, @ConditionalOnSingleCandidate,该注解表示当指定Bean在容器中只有一个,或者虽然有多个但是指定首选Bean。因为在自定义的redis配置类有3个redisFactory,并且没有指定首选,所以配置redisTemplate、stringRedisTemplate失败,破案!