如題,升級了一下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);
? ? }
}