1.问题起因

目前写SPringBoot引入多数据源路由
遇到了需要控制加载顺序的问题

@Configuration
@MapperScan(basePackages = "com.gaotianyue.dao")
public class DataSourceConfig {第一步@Bean@ConfigurationProperties(prefix = "spring.datasource")public DataSource dataSource1() {return DataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix = "spring.datasource")public DataSource dataSource2() {return = DataSourceBuilder.create().build();}
}
@Configuration
public class RoutingDataSourceConfig {第二步@Bean(name="rwDataSource")public ReadWriteRoutingDataSource rwDataSource(@Qualifier("dataSource1") DataSource dataSource1, @Qualifier("dataSource2") DataSource dataSource2) {ReadWriteRoutingDataSource ds = new ReadWriteRoutingDataSource();Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put(Master.class, dataSource1);targetDataSources.put(Slave.class, dataSource2);ds.setTargetDataSources(targetDataSources);ds.setDefaultTargetDataSource(dataSource1);//默认数据源return ds;}第三部报错@Beanpublic SqlSessionFactory ds1SqlSessionFactory(@Qualifier("rwDataSource") ReadWriteRoutingDataSource dataSource) throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(dataSource);bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*.xml"));return bean.getObject();}
}

两段程序本来在一个类中
引用情况如下:

            |----<>SqlSessionFactoryBean ||<>-- -- DataSource|           /|\|            ||<>-- -- RWRoutingDataSoure||<>---DataSource

启动后发现出现循环引用错误
单独保留DataSource RWRoutingDataSoure的配置没有问题,一旦SqlSessionFactoryBean从参数注入RWRoutingDataSoure 就会爆出

Error creating bean with name 'rwDataSource': Requested bean is currently in creation: Is there an unresolvable circular reference?

首先想到控制加载顺序的问题。首先想到@AutoConfigureAfter({DataSourceConfig.class})这一注解,但是加上这一注解是无效的。即使有不少人使用了@AutoConfigureAfter({DataSourceConfig.class}) + @Configuration的配置,其实并未起到作用。阅资料还需要配置spring.factories文件,
META-INF/spring.factories

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.gaotianyue.autoconfigure.DataSourceConfig,\
com.gaotianyue.autoconfigure.RoutingDataSourceConfig

修改App.java使配置类的路径不能被SpringBootApplication扫描。

@SpringBootApplication(scanBasePackages={"com.gaotianyue.manager"})
public class App {public static void main(String[] args) throws Exception {AppStarter.initManagers(SpringApplication.run(App.class, args));}
}

但是 依然“不能够控制加载顺序!”

目前循环依赖的起因初步判断跟
org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer有关

@PostConstructpublic void init() {if (!this.properties.isInitialize()) {logger.debug("Initialization disabled (not running DDL scripts)");return;}if (this.applicationContext.getBeanNamesForType(DataSource.class, false,false).length > 0) {this.dataSource = this.applicationContext.getBean(DataSource.class);}if (this.dataSource == null) {logger.debug("No DataSource found so not initializing");return;}runSchemaScripts();}

和Object org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerPostProcessor.postProcessAfterInitialization(Object bean, String beanName) throws BeansException

    @Overridepublic Object postProcessAfterInitialization(Object bean, String beanName)throws BeansException {if (bean instanceof DataSource) {// force initialization of this bean as soon as we see a DataSourcethis.beanFactory.getBean(DataSourceInitializer.class);}return bean;}

有关,正在努力测试中

解决方案1

/*** 读写分离数据源配置*/
@Configuration
//@EnableTransactionManagement //事务
@MapperScan(basePackages = "com.vipkid.coursera.manager.dao")//scan
public class DataSourceConfig {public DataSourceConfig(){LogCore.BASE.info("myabtis multiple datasources configure start !");}@Bean@ConfigurationProperties(prefix = "spring.datasource")public DataSource dataSource1() {DataSource ds = (DataSource) DataSourceBuilder.create().build();LogCore.BASE.info("dataSource1.hashCode={}", Util.objString(ds));return ds;}@Bean@ConfigurationProperties(prefix = "spring.datasource")public DataSource dataSource2() {DataSource ds = (DataSource) DataSourceBuilder.create().build();LogCore.BASE.info("dataSource2.hashCode={}", Util.objString(ds));return ds;}/**装配路由数据源*/@Bean(name="rwDataSource")@Autowiredpublic DataSourceBeanWrapper<ReadWriteDataSourceRouter> rwDataSource(@Qualifier("dataSource1") DataSource dataSource1, @Qualifier("dataSource2") DataSource dataSource2) {ReadWriteDataSourceRouter ds = new ReadWriteDataSourceRouter();Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put(Master.class, dataSource1);targetDataSources.put(Slave.class, dataSource2);ds.setTargetDataSources(targetDataSources);ds.setDefaultTargetDataSource(dataSource1);//默认数据源DataSourceBeanWrapper<ReadWriteDataSourceRouter> t = new DataSourceBeanWrapper<>(ds);return t;}@Beanpublic SqlSessionFactory ds1SqlSessionFactory(DataSourceBeanWrapper<ReadWriteDataSourceRouter> dataSource1) throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(dataSource1.getDataSource());bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappers/**/*.xml"));return bean.getObject();}@Bean(name = "ds1TransactionManager")public DataSourceTransactionManager ds1TransactionManager(@Qualifier("rwDataSource") DataSourceBeanWrapper<ReadWriteDataSourceRouter> dataSource1) {return new DataSourceTransactionManager(dataSource1.getDataSource());}@PostConstruct void after(){LogCore.BASE.info("myabtis multiple datasources configure after !");}
}
public final class DataSourceBeanWrapper<T extends DataSource> implements InitializingBean{private T dataSource;public DataSourceBeanWrapper(T realDataSource) {super();this.dataSource = realDataSource;}public T getDataSource() {return dataSource;}public void setDataSource(T dataSource) {this.dataSource = dataSource;}@Overridepublic void afterPropertiesSet() throws Exception{if (this.dataSource == null) {throw new IllegalArgumentException("Property 'dataSources' is required");}if(this.dataSource instanceof InitializingBean){((InitializingBean)dataSource).afterPropertiesSet();}}@Overridepublic String toString() {StringBuilder builder = new StringBuilder();builder.append("DataSourceBeanWrapper =");builder.append(getClass().getName() + "@" + Integer.toHexString(hashCode()));builder.append("; dataSource=");builder.append(dataSource);return builder.toString();}
}

解决方案2

Configuration
//@EnableTransactionManagement //事务
@MapperScan(basePackages = "com.vipkid.coursera.manager.dao")//scan
public class DataSourceConfig {public DataSourceConfig(){LogCore.BASE.info("myabtis multiple datasources configure start !");}@Bean(name="dataSource1")@ConfigurationProperties(prefix = "spring.datasource")public DataSource dataSource1() {DataSource ds = DataSourceBuilder.create().build();LogCore.BASE.info("dataSource1.hashCode={}", Util.objString(ds));return ds;}@Bean@ConfigurationProperties(prefix = "spring.datasource")public DataSource dataSource2() {DataSource ds = DataSourceBuilder.create().build();LogCore.BASE.info("dataSource2.hashCode={}", Util.objString(ds));return ds;}/*** 装配路由数据源* @see {@link DataSourceBeanWrapper}*/@Bean@DependsOn({ "dataSource1", "dataSource2"})public DataSource rwDataSource() {ReadWriteDataSourceRouter ds = new ReadWriteDataSourceRouter();Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put(Master.class, dataSource1());targetDataSources.put(Slave.class, dataSource2());ds.setTargetDataSources(targetDataSources);ds.setDefaultTargetDataSource(dataSource1());//默认数据源LogCore.BASE.info("ReadWriteDataSourceRouter init ={}", ds);return ds;}@Beanpublic SqlSessionFactory ds1SqlSessionFactory(DataSource rwDataSource) throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(rwDataSource);bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappers/**/*.xml"));return bean.getObject();}@Bean(name = "ds1TransactionManager")public DataSourceTransactionManager ds1TransactionManager(@Qualifier("rwDataSource") DataSource rwDataSource) {return new DataSourceTransactionManager(rwDataSource);}@PostConstruct void after(){LogCore.BASE.info("myabtis multiple datasources configure after !");}
}

Spring boot (21)多数据源引起的循环引用和AutoConfigureAfter失效的问题相关推荐

  1. 【方向盘】Spring Boot 2.6.0正式发布,循环引用终于被禁

    天再高又怎样,踮起脚尖就更接近阳光. 本文已被https://yourbatman.cn收录:女娲Knife-Initializr工程可公开访问啦:程序员专用网盘https://wangpan.you ...

  2. java多个数据库数据进行访问_通过Spring Boot配置动态数据源访问多个数据库的实现代码...

    之前写过一篇博客<Spring+Mybatis+Mysql搭建分布式数据库访问框架>描述如何通过Spring+Mybatis配置动态数据源访问多个数据库.但是之前的方案有一些限制(原博客中 ...

  3. mysql 多数据源访问_通过Spring Boot配置动态数据源访问多个数据库的实现代码

    之前写过一篇博客<Spring+Mybatis+Mysql搭建分布式数据库访问框架>描述如何通过Spring+Mybatis配置动态数据源访问多个数据库.但是之前的方案有一些限制(原博客中 ...

  4. spring boot项目自定义数据源,mybatisplus分页、逻辑删除无效解决方法

    Spring Boot项目中数据源的配置可以通过两种方式实现: 1.application.yml或者application.properties配置 2.注入DataSource及SqlSessio ...

  5. boot jndi数据源 spring_使用Spring Boot配置JNDI数据源 -Roy教程

    在这篇文章中,我们将看到如何使用Spring Boot配置JNDI数据源.JNDI数据源与JDBC数据源非常相似.JNDI数据源访问在应用程序服务器中预定义和配置并作为JNDI资源或服务发布的数据库连 ...

  6. spring boot 动态切换数据源实现多租户开发

    之前的文章有介绍过spring boot 动态切换数据源spring boot 动态切换数据源(数据源信息从数据库中读取)_lgq2016的博客-CSDN博客,今天简单介绍一下动态数据源切换实战,主要 ...

  7. Spring Boot使用动态数据源

    文章目录 前言 一.什么是动态数据源 二.动态数据源实现 1.实现原理 2.实现过程 前言 有这样一个场景,现在要开发一个数据API功能,用户自己编写数据源脚本,在界面任意选择一个数据源,可选择的数据 ...

  8. Spring Boot Jpa多数据源配置

    2019独角兽企业重金招聘Python工程师标准>>> 前言 随着业务量发展,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源,如:user一个库,busine ...

  9. Spring Boot笔记-自动配置(Spring Boot封装成jar被其他项目引用)

    特点: 这里也就是自己写个Service注册到别人的SpringBoot项目中,然后别人来调用这个Service,这个Service,先读取自己的application.properties,再读取引 ...

最新文章

  1. php上传文件到七牛云
  2. Chapter4:Using Standard Control(学习)
  3. ResNet Keras实现
  4. 李彦宏:自动驾驶是起点,终局是智能交通;iPhone15将搭载苹果自研5G基带芯片;英特尔收购Linutronix|极客头条...
  5. WPF RadioButton按钮控件取消选中设置
  6. qt与duilib对比
  7. 管家婆服务器支持win7,Windows7多种措施 打造无敌驱动管家婆
  8. Java多线程系列--【JUC线程池 03】- 线程池原理(二)
  9. [转] 大学的终结—1950年代初期的“院系调整”
  10. 劫持 64 位静态程序 fini_array 进行 ROP 攻击
  11. 小鹏用计算机计算38X596时,物理化学-表面化学部分选择题
  12. 华为路由交换学习篇-路由
  13. pcl_viewer的使用
  14. iOS9 3D Touch 标签菜单 peek and pop force 压力触控 功能开发高级版教程
  15. Glide v4详解
  16. MATLAB希尔伯特矩阵和逆希尔伯特矩阵
  17. Python到pyspark中的py-files的问题
  18. php向js的函数内传递参数-用经纬度计算2点间的距离
  19. lv双肩包尺寸对照表_最值得入手的10款LV双肩包包书包图片大全
  20. 2019.4.4【母亲进入了癫狂状态】

热门文章

  1. 模糊数学 计算机智能,《常用算法之智能计算 (五) 》:模糊计算
  2. 阿里云服务器修改名称
  3. 页面可视化搭建工具业界的轮子
  4. 计算机网络启动慢,台式电脑开机网络连接慢的解决办法
  5. 台式电脑怎么添加计算机硬盘,台式机怎么加硬盘 台式机加硬盘教程介绍【图文详解】...
  6. The following packages have unmet dependencies问题
  7. Day_03——MySQL数据库查询语句练习
  8. 异构网络互联;路由与转发;SDN基本概念;拥塞控制
  9. 制作条形码的手机App推荐
  10. 一本值得反复学习的好书——《重构》读后感