在 Spring Boot 中,DataSourceAutoConfiguration
是单数据源情况下的默认自动配置类。当引入多数据源方案(例如 dynamic-datasource-spring-boot-starter
)后,单数据源的自动配置机制会失效,原因主要在于多数据源自动配置类的优先加载和 Spring Boot 的条件装配逻辑。
1. 单数据源的自动配置机制
Spring Boot 的 DataSourceAutoConfiguration
是为单数据源提供的默认配置,依赖以下核心注解:
@ConditionalOnMissingBean
自动配置的核心条件之一,只有在容器中不存在DataSource
或XADataSource
实例(对象)的情况下,Spring 才会装配默认的数据源。
关键代码如下:
java">@Configuration(proxyBeanMethods = false
)
@Conditional({PooledDataSourceCondition.class})
@ConditionalOnMissingBean({DataSource.class, XADataSource.class})
@Import({DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class, DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class})
protected static class PooledDataSourceConfiguration {protected PooledDataSourceConfiguration() {}@Bean@ConditionalOnMissingBean({JdbcConnectionDetails.class})PropertiesJdbcConnectionDetails jdbcConnectionDetails(DataSourceProperties properties) {return new PropertiesJdbcConnectionDetails(properties);}
}
核心逻辑:
如果容器中已经存在 DataSource
或 XADataSource
实例(对象)的情况下,上述配置将不会生效。这是为了避免重复配置或冲突。
2. 多数据源的自动配置机制
当引入 dynamic-datasource-spring-boot-starter
后,自动配置类 DynamicDataSourceAutoConfiguration
会使得 DataSourceAutoConfiguration
自动配置类中加载数据源失效。
DynamicDataSourceAutoConfiguration
类的定义如下:
java">@AutoConfigureBefore(value = DataSourceAutoConfiguration.class,name = "com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure"
)
public class DynamicDataSourceAutoConfiguration implements InitializingBean {// 动态数据源的配置逻辑
}
@AutoConfigureBefore
确保DynamicDataSourceAutoConfiguration
在DataSourceAutoConfiguration
之前加载。且DynamicDataSourceAutoConfiguration
在容器初始化时,会预先创建和注册动态数据源的DataSource
实例,这使得@ConditionalOnMissingBean
的条件不再满足。所以DataSourceAutoConfiguration
中的自动注入数据源就无法生效。
3. 为什么单数据源的自动配置类失效?
单数据源的自动配置类失效的原因可以归结为以下几点:
3.1 动态数据源的优先加载
@AutoConfigureBefore
明确指示 DynamicDataSourceAutoConfiguration
在默认的 DataSourceAutoConfiguration
之前加载。因此,动态数据源配置优先于单数据源配置完成初始化。
3.2 提前注入 DataSource
Bean
在动态数据源方案中,DynamicDataSourceAutoConfiguration
会在 DataSourceAutoConfiguration
执行前,向容器注册一个动态的 DataSource
Bean(通常是 DynamicRoutingDataSource
)。这使得 @ConditionalOnMissingBean(DataSource.class)
的条件不再满足,导致单数据源的自动配置逻辑被跳过。
3.3 替代单数据源配置
动态数据源的目标是支持多个数据源,同时提供路由、切换等功能。而单数据源的默认配置显然无法满足这些需求,因此被动态数据源框架的配置完全替代。
4. 总结
在引入 dynamic-datasource-spring-boot-starter
后,单数据源的自动配置类失效的根本原因是多数据源自动配置类的优先加载和条件装配的逻辑冲突。具体表现如下:
- 优先加载:多数据源通过
@AutoConfigureBefore
指定在单数据源自动配置之前加载。 - 条件不满足:多数据源自动配置类提前注册了
DataSource
,使得DataSourceAutoConfiguration
的@ConditionalOnMissingBean
条件不成立。 - 逻辑替代:多数据源需要更复杂的配置逻辑,单数据源配置被替代。
这种机制是 Spring Boot 条件装配机制和自动配置优先级协同工作的结果,也是动态数据源实现灵活性的重要基础。