SpringBoot数据源连接池的加载

it2026-08-24  3

官网原话:

Production database connections can also be auto-configured by using a pooling DataSource. Spring Boot uses the following algorithm for choosing a specific implementation:

We prefer HikariCP for its performance and concurrency. If HikariCP is available, we always choose it.Otherwise, if the Tomcat pooling DataSource is available, we use it.If neither HikariCP nor the Tomcat pooling datasource are available and if Commons DBCP2 is available, we use it.

If you use the spring-boot-starter-jdbc or spring-boot-starter-data-jpa “starters”, you automatically get a dependency to HikariCP.

在获取数据库连接时,可以通过使用数据源连接池来自动获取。

SpringBoot自动配置的连接池的顺序:

HikariCPTomcat poolingDBCP2

同样可以直接使用starters来配置

源码解释

我们这里使用的springBoot 2.3.4版本

springboot中JDBC的自动配置类是DataSourceHealthContributorAutoConfiguration

@Configuration(proxyBeanMethods = false) @ConditionalOnClass({ JdbcTemplate.class, AbstractRoutingDataSource.class }) @ConditionalOnBean(DataSource.class) @ConditionalOnEnabledHealthIndicator("db") @AutoConfigureAfter(DataSourceAutoConfiguration.class) public class DataSourceHealthContributorAutoConfiguration extends CompositeHealthContributorConfiguration<AbstractHealthIndicator, DataSource> implements InitializingBean {

DataSourceAutoConfiguration包含有数据源的自动配置

@Configuration(proxyBeanMethods = false) @ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class }) @ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory") @EnableConfigurationProperties(DataSourceProperties.class) @Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class }) public class DataSourceAutoConfiguration { @Configuration(proxyBeanMethods = false) @Conditional(EmbeddedDatabaseCondition.class) @ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) @Import(EmbeddedDataSourceConfiguration.class) protected static class EmbeddedDatabaseConfiguration { } @Configuration(proxyBeanMethods = false) @Conditional(PooledDataSourceCondition.class) @ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) @Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class }) protected static class PooledDataSourceConfiguration { }

PooledDataSourceConfiguration的 DataSourceConfiguration数据源配置中分别包含了Hikari,Tomcat,Dbcp2,Generic。

abstract class DataSourceConfiguration { @SuppressWarnings("unchecked") protected static <T> T createDataSource(DataSourceProperties properties, Class<? extends DataSource> type) { return (T) properties.initializeDataSourceBuilder().type(type).build(); } /** * Tomcat Pool DataSource configuration. */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class) @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true) static class Tomcat { @Bean @ConfigurationProperties(prefix = "spring.datasource.tomcat") org.apache.tomcat.jdbc.pool.DataSource dataSource(DataSourceProperties properties) { org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource(properties, org.apache.tomcat.jdbc.pool.DataSource.class); DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(properties.determineUrl()); String validationQuery = databaseDriver.getValidationQuery(); if (validationQuery != null) { dataSource.setTestOnBorrow(true); dataSource.setValidationQuery(validationQuery); } return dataSource; } } /** * Hikari DataSource configuration. */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(HikariDataSource.class) @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true) static class Hikari { @Bean @ConfigurationProperties(prefix = "spring.datasource.hikari") HikariDataSource dataSource(DataSourceProperties properties) { HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class); if (StringUtils.hasText(properties.getName())) { dataSource.setPoolName(properties.getName()); } return dataSource; } } /** * DBCP DataSource configuration. */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(org.apache.commons.dbcp2.BasicDataSource.class) @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.commons.dbcp2.BasicDataSource", matchIfMissing = true) static class Dbcp2 { @Bean @ConfigurationProperties(prefix = "spring.datasource.dbcp2") org.apache.commons.dbcp2.BasicDataSource dataSource(DataSourceProperties properties) { return createDataSource(properties, org.apache.commons.dbcp2.BasicDataSource.class); } } /** * Generic DataSource configuration. */ @Configuration(proxyBeanMethods = false) @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type") static class Generic { @Bean DataSource dataSource(DataSourceProperties properties) { return properties.initializeDataSourceBuilder().build(); } } }

springBoot默认导入的是Hikari。其它连接池如果需要,必须在pom文件中导入。

其中createDataSource方法是创建数据源。我们单独再拿出来

@SuppressWarnings("unchecked") protected static <T> T createDataSource(DataSourceProperties properties, Class<? extends DataSource> type) { return (T) properties.initializeDataSourceBuilder().type(type).build(); }

在类DataSourceBuilder中存在build()。

public T build() { Class<? extends DataSource> type = getType(); DataSource result = BeanUtils.instantiateClass(type); maybeGetDriverClassName(); bind(result); return (T) result; }

getType()

private Class<? extends DataSource> getType() { //private Class<? extends DataSource> type; //在没有配置type的情况下type=findType(this.classLoader)。 //当存在type时使用预先定义的type作为数据源连接池 Class<? extends DataSource> type = (this.type != null) ? this.type : findType(this.classLoader); if (type != null) { return type; } throw new IllegalStateException("No supported DataSource type found"); }

findType()

public static Class<? extends DataSource> findType(ClassLoader classLoader) { /*private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] { "com.zaxxer.hikari.HikariDataSource", "org.apache.tomcat.jdbc.pool.DataSource", "org.apache.commons.dbcp2.BasicDataSource" }; */ //在存在com.zaxxer.hikari.HikariDataSource的情况下默认是拿到hikari的数据源连接池后返回。 for (String name : DATA_SOURCE_TYPE_NAMES) { try { return (Class<? extends DataSource>) ClassUtils.forName(name, classLoader); } catch (Exception ex) { // Swallow and continue } } return null; }

总结

当自己需要自定义配置数据源时有两种方法。

是直接使用某个数据源的启动器导入相依数据源连接池的依赖,使用spring.datasource.type=数据源连接池。进行预先配置
最新回复(0)