博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
记一次 Spring Boot多数据源 循环引用问题
阅读量:6496 次
发布时间:2019-06-24

本文共 5089 字,大约阅读时间需要 16 分钟。

hot3.png

如题,升级了一下mybatis版本后出现循环引用的问题。

具体异常如下

***************************APPLICATION FAILED TO START***************************Description:The dependencies of some of the beans in the application context form a cycle:     略      ↓   sqlSessionFactory defined in class path resource [com/suike/config/database/MyBatisConfig.class]┌─────┐|  dataSource defined in class path resource [com/suike/config/database/MyBatisConfig.class]↑     ↓|  dataSourceDev defined in class path resource [com/suike/config/database/dataSource/DruidDBConfigDev.class]↑     ↓|  dataSourceInitializer└─────┘然后抛出一堆的:org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceDev' defined in class path resource [xxx类]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceInitializer': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'dataSource': Requested bean is currently in creation: Is there an unresolvable circular reference?

 

我的配置一共3个,前两个是数据源,第3个是Mybatis的配置类

@Configurationpublic class DruidDBConfigDev {    @Bean(name="dataSourceDev")    public DruidDataSource dataSource(){        DruidDataSource datasource = new DruidDataSource();		//略        return datasource;    }}
@Configurationpublic class DruidDBConfigProd {    @Bean(name="dataSourceProd")    public DruidDataSource dataSource(){        DruidDataSource datasource = new DruidDataSource();		//略        return datasource;    }}
@Configuration() @MapperScan(value = "com.suike.mapper")public class MyBatisConfig {    //重点在这个方法    @Bean    @Primary    public DynamicDataSource dataSource(@Qualifier("dataSourceDev") DataSource dataSourceDev,                                        @Qualifier("dataSourceProd") DataSource dataSourceProd) {        Map
targetDataSources = new HashMap<>(); targetDataSources.put(DatabaseType.dataSourceDev, dataSourceDev); targetDataSources.put(DatabaseType.dataSourceProd, dataSourceProd); DynamicDataSource dataSource = new DynamicDataSource(); dataSource.setTargetDataSources(targetDataSources);// 该方法是AbstractRoutingDataSource的方法 dataSource.setDefaultTargetDataSource(dataSourceDev);// 默认的datasource设置为myTestDbDataSource return dataSource; } /** * 根据数据源创建SqlSessionFactory */ @Bean public SqlSessionFactory sqlSessionFactory(DynamicDataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); return sessionFactory.getObject(); } @Bean public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } /** * 配置事务管理器 */ @Bean public DataSourceTransactionManager transactionManager(DynamicDataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean public TransactionTemplate txTemplate(DataSourceTransactionManager transactionManager) { return new TransactionTemplate(transactionManager); }}

 

看完3个配置,再回过头来看异常信息

┌─────┐

|  dataSource defined in class path resource [com/suike/config/database/MyBatisConfig.class]
↑     ↓
|  dataSourceDev defined in class path resource [com/suike/config/database/dataSource/DruidDBConfigDev.class]
↑     ↓
|  dataSourceInitializer
└─────┘

看起来意思就是MyBatisConfig需要依赖DruidDBConfigDev数据源,而DruidDBConfigDev数据源创建的时候又需要依赖这个dataSourceInitializer。

但是dataSourceInitializer又需要依赖MyBatisConfig

 

 

解决方案1:

不要把数据源注入spring,直接在配置类配置数据源的方法里new一个数据源

如:

/**     * @Primary 指定在同一个接口有多个实现类可以注入的时候,默认选择哪一个,而不是让@Autowire注解报错(一般用于多数据源的情况下)     * @Qualifier 根据名称进行注入,通常是在具有相同的多个类型的实例的一个注入(例如有多个DataSource类型的实例)     */    @Bean    @Primary    public DynamicDataSource dataSource() {        DruidDataSource datasource1 = new DruidDataSource();        datasource1.setUrl("");        datasource1.setUsername("");        datasource1.setPassword("");        datasource1.setDriverClassName("com.mysql.jdbc.Driver");        DruidDataSource datasource2 = new DruidDataSource();        //略        Map
targetDataSources = new HashMap<>(); targetDataSources.put(DatabaseType.dataSourceDev, datasource1); targetDataSources.put(DatabaseType.dataSourceProd, datasource2); DynamicDataSource dataSource = new DynamicDataSource(); dataSource.setTargetDataSources(targetDataSources);// 该方法是AbstractRoutingDataSource的方法 dataSource.setDefaultTargetDataSource(datasource1);// 默认的datasource设置为myTestDbDataSource return dataSource; }

 

解决方案2(推荐):

保持原来的配置,在Spring boot启动的时候排除DataSourceAutoConfiguration,并另外导入MyBatisConfig

@Import({MyBatisConfig.class})@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})public class App extends SpringBootServletInitializer {    public static void main(String[] args) {        SpringApplication.run(App.class, args);    }}

 

 

转载于:https://my.oschina.net/yejunxi/blog/2885730

你可能感兴趣的文章
为什么sql里面not in后面的子查询如果有记录为NULL的,主查询就查不到记录
查看>>
Angular7里面实现 debounce search
查看>>
Linux 内核链表
查看>>
git学习------>Git 分支管理最佳实践
查看>>
括号和出栈所有序列问题
查看>>
第一次操刀数据库分表的教训与经验
查看>>
录音声音小
查看>>
Ubuntu 12.04 安装 Chrome浏览器
查看>>
java 反射
查看>>
ORACLE物化视图(物理视图)
查看>>
android 读取json数据(遍历JSONObject和JSONArray)(转)
查看>>
UIScrollView中的手势
查看>>
递归和迭代的差别
查看>>
基于jquery的可拖动div
查看>>
可以简易设置文字内边距的EdgeInsetsLabel
查看>>
[詹兴致矩阵论习题参考解答]习题1.3
查看>>
Android Fragment的使用
查看>>
mysql半同步复制实现
查看>>
沙朗javascript总结一下(一)---基础知识
查看>>
js深入研究之函数内的函数
查看>>