Spring cloud 和 Spring Boot 升级到F版和2.x遇到的问题。
时间: 2018-08-02
今天一个朋友升级Spring Cloud 到F版 出现的问题,
1、问题一
1)、大概错误:
is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthIndicatorAutoConfiguration’: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthIndicatorAutoConfiguration$$EnhancerBySpringCGLIB$$e550fa6]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘dataSource’: Post-processing of FactoryBean’s singleton object failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘scopedTarget.dataSource’ defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Initialization of bean failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker’: Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘dataSource’: Post-processing of FactoryBean’s singleton object failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ‘scopedTarget.dataSource’: Requested bean is currently in creation: Is there an unresolvable circular reference?
2)解决方案: 将spring boot 升级到2.0.4 即可解决
相关解决问题地址: https://github.com/spring-cloud/spring-cloud-commons/issues/384
实际是在spring 5.0.8 中的获取bean 进行调整
org\springframework\spring-beans\5.0.8.RELEASE\spring-beans-5.0.8.RELEASE.jar!\org\springframework\beans\factory\support\AbstractBeanFactory.class
2、问题二
1)、出现的spring-data-redis 的切库问题:
Selecting a new database not supported due to shared connection. Use separate ConnectionFactorys to work with multiple databases
原因是 spring boot 2.x 默认是用的是 LettuceConnection , 这个是使用共享连接的,所以会出现上面的错误。
2)定位和解决方案:
通过访问地址:
https://docs.spring.io/spring-data/redis/docs/2.1.0.M3/reference/html/#new-in-2.0.0
可以到2.0 的特性信息,具体如图1所示:
图1
redisConnectionFactory 有两个实现类, 具体如图2所示:
图2
因为Sprig Boot 2.x 使用的是LettuceConnnection, 所以会使用LettuceConnectionFactory,那么这个工厂类是在哪里是初始化呢?
是在LettuceConnectionConfiguration 中进行初始化的, 具体如图3所示:
图3
接下来, 在看看LettuceConnnection 是在哪里进行切换数据库的, 具体如图4所示:
图4
红框部分就是上述打印出来的错误, 那么, 问题就定位到了, 看看上述参数如何设置的。
图5
从上图5中可以知道, 是在构造方法中进行初始化的。 问题又回到了LettuceConnectionFactory里面,具体是在图6所示位置创建。
图6
从图6可以看到shareNativeConnection 这个变量决定是否要创建一个新的连接, 这个值默认是true 共享连接。
具体如何设置呢?请看图7。
到此就分析完成个过程了,接下来看看解决方案。
解决方法1:
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisCacheAutoConfiguration {
@Bean
public RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
redisConnectionFactory.setShareNativeConnection(false);
RedisTemplate<String, Serializable> template = new RedisTemplate<>();
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
解决方法2:
自己构建LettuceConnectionFactory
@Configuration
public class Factory{
@Bean
@ConditionalOnClass(RedisConnectionFactory.class)
public LettuceConnectionFactory redisConnectionFactory(
ClientResources clientResources) throws UnknownHostException {
// 这里创建factory, 具体创建需要的参数参考图3
}
}
到此整个升级过程的遇到的bug就都解决完成。