Spring Boot多數(shù)據(jù)源 循環(huán)引用問題

如題,升級了一下mybatis版本后出現(xiàn)循環(huán)引用的問題。

具體異常如下

***************************APPLICATION FAILED TO START***************************Description:Thedependenciesofsomeofthebeansintheapplication 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類]: Initializationofbean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceInitializer': Invocationofinit 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個,前兩個是數(shù)據(jù)源,第3個是Mybatis的配置類

@Configuration

public class DruidDBConfigDev {

? ? @Bean(name="dataSourceDev")

? ? public DruidDataSource dataSource(){

? ? ? ? DruidDataSource datasource = new DruidDataSource();

//略

? ? ? ? return datasource;

? ? }

}

@Configuration

public 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<Object, Object> 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;

? ? }

? ? /**

? ? * 根據(jù)數(shù)據(jù)源創(chuàng)建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數(shù)據(jù)源,而DruidDBConfigDev數(shù)據(jù)源創(chuàng)建的時候又需要依賴這個dataSourceInitializer。

但是dataSourceInitializer又需要依賴MyBatisConfig



解決方案1:

不要把數(shù)據(jù)源注入spring,直接在配置類配置數(shù)據(jù)源的方法里new一個數(shù)據(jù)源

如:

? ? /**

? ? * @Primary 指定在同一個接口有多個實現(xiàn)類可以注入的時候,默認選擇哪一個,而不是讓@Autowire注解報錯(一般用于多數(shù)據(jù)源的情況下)

? ? * @Qualifier 根據(jù)名稱進行注入,通常是在具有相同的多個類型的實例的一個注入(例如有多個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<Object, Object> 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);

? ? }

}

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容