如题,升级了一下mybatis版本后出现循环引用的问题。
具体异常如下
***************************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个,前两个是数据源,第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;
}
/**
* 根据数据源创建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<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);
}
}
网友评论