Spring Boot多数据源 循环引用问题

如题,升级了一下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);

    }

}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容