Springboot DataSources 自动配置原理
Springboot DataSources 自动配置原理
本文通过阅读SpringBoot源码分析了Springboot中DataSources的自动配置原理
DataSources自动配置原理
配置文件 application.yml
配置数据源配置
application.yml
spring:
datasource:
url: jdbc:mysql//127.0.0.1:3306/test
username: root
password: 123456
type: com.mysql.cj.jdbc.MysqlDataSource
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.java
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@ConditionalOnMissingBean(
type = {"io.r2dbc.spi.ConnectionFactory"}
)
// 以上两个注解指明了当DataSource.class, EmbeddedDatabaseType.class两个类存在且io.r2dbc.spi.ConnectionFactory类型的Bean不存在时 @Configuration注解才会生效
@AutoConfigureBefore({SqlInitializationAutoConfiguration.class})
// 指明当前配置类将在`SqlInitializationAutoConfiguration.class`加载之前加载
@EnableConfigurationProperties({DataSourceProperties.class})
// 指明自动注入带有ConfigurationProperties注解的DataSourceProperties类
@Import({DataSourcePoolMetadataProvidersConfiguration.class, InitializationSpecificCredentialsDataSourceInitializationConfiguration.class, SharedCredentialsDataSourceInitializationConfiguration.class})
// 将注解中的类导入到IOC容器中
public class DataSourceAutoConfiguration {
/** 略... **/
@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 })
// 加载 DataSourceConfiguration下的静态类时,根据相应静态类的注解条件进行加载
protected static class PooledDataSourceConfiguration {
}
static class PooledDataSourceCondition extends AnyNestedCondition {
PooledDataSourceCondition() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
}
@ConditionalOnProperty(prefix = "spring.datasource", name = "type")
static class ExplicitType {
}
@Conditional(PooledDataSourceAvailableCondition.class)
static class PooledDataSourceAvailable {
}
}
static class PooledDataSourceAvailableCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage.forCondition("PooledDataSource");
if (DataSourceBuilder.findType(context.getClassLoader()) != null) {
return ConditionOutcome.match(message.foundExactly("supported DataSource"));
}
return ConditionOutcome.noMatch(message.didNotFind("supported DataSource").atAll());
}
}
/** 略... **/
}
以DataSourceConfiguration
下的通用数据源为例,源码如下:
org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.java
abstract class DataSourceConfiguration {
/** 略... **/
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type")
// 当DataSource类型的Bean不存在且配置文件存在"spring.datasource.type"配置时 创建通用类型数据源
static class Generic {
@Bean
DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
}
org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.java
@ConfigurationProperties(prefix = "spring.datasource")
// 加载"spring.datasource"前缀的配置
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
/** 略... **/
// 从此方法可以得知 数据源是由 DataSourceBuilder 类来构建的
public DataSourceBuilder<?> initializeDataSourceBuilder() {
return DataSourceBuilder.create(getClassLoader()).type(getType()).driverClassName(determineDriverClassName())
.url(determineUrl()).username(determineUsername()).password(determinePassword());
}
/** 略... **/
}
org.springframework.boot.jdbc.DataSourceBuilder
类中包含了数据源创建的具体实现 有兴趣的请自行探究
总结: Springboot DataSources 的自动配置流程大致为
Springboot在启动后 扫描到带有 @Configuration
注解的 DataSourceAutoConfiguration
类
满足一定条件的DataSourceAutoConfiguration
类将DataSourceProperties
带入IOC容器并加载application.yml
文件中的配置
DataSourceAutoConfiguration.PooledDataSourceConfiguration
在加载时将DataSourceConfiguration
下的静态类引入IOC容器
DataSourceConfiguration
下的静态类根据条件进行加载,各种数据源的创建方式由spring.datasource.type
填写的类决定
除Generic
(通用方式)外,Springboot内置的数据源仅支持 Tomcat
,Hikari
,Dbcp2
,OracleUcp
四种
如误请指正!