Spring Boot 2.0 默认使用 com.zaxxer.hikari.HikariDataSource 数据源
Spring Boot 1.5 默认使用 org.apache.tomcat.jdbc.pool.DataSource 作为数据源;
DataSourceConfiguration 源代码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.boot.autoconfigure.jdbc;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.context.annotation.Bean;
import org.springframework.util.StringUtils;
abstract class DataSourceConfiguration {
DataSourceConfiguration() {
}
protected static <T> T createDataSource(DataSourceProperties properties, Class<? extends DataSource> type) {
return properties.initializeDataSourceBuilder().type(type).build();
}
//自定义连接池 接口 spring.datasource.type 配置
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name = {"spring.datasource.type"}
)
static class Generic {
Generic() {
}
@Bean
public DataSource dataSource(DataSourceProperties properties) {
//创建数据源 initializeDataSourceBuilder DataSourceBuilder
return properties.initializeDataSourceBuilder().build();
}
}
//Dbcp2 连接池
@ConditionalOnClass({BasicDataSource.class})
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name = {"spring.datasource.type"},
havingValue = "org.apache.commons.dbcp2.BasicDataSource",
matchIfMissing = true
)
static class Dbcp2 {
Dbcp2() {
}
@Bean
@ConfigurationProperties(
prefix = "spring.datasource.dbcp2"
)
public BasicDataSource dataSource(DataSourceProperties properties) {
return (BasicDataSource)DataSourceConfiguration.createDataSource(properties, BasicDataSource.class);
}
}
//2.0 之后默认默认使用 hikari 连接池
@ConditionalOnClass({HikariDataSource.class})
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name = {"spring.datasource.type"},
havingValue = "com.zaxxer.hikari.HikariDataSource",
matchIfMissing = true
)
static class Hikari {
Hikari() {
}
@Bean
@ConfigurationProperties(
prefix = "spring.datasource.hikari"
)
public HikariDataSource dataSource(DataSourceProperties properties) {
HikariDataSource dataSource = (HikariDataSource)DataSourceConfiguration.createDataSource(properties, HikariDataSource.class);
if (StringUtils.hasText(properties.getName())) {
dataSource.setPoolName(properties.getName());
}
return dataSource;
}
}
//2.0 之后默认不是使用 tomcat 连接池,或者使用tomcat 容器
//如果导入tomcat jdbc连接池 则使用此连接池,在使用tomcat容器时候 或者导入此包时候
@ConditionalOnClass({org.apache.tomcat.jdbc.pool.DataSource.class})
@ConditionalOnMissingBean({DataSource.class})
//并且配置的配置是 org.apache.tomcat.jdbc.pool.DataSource 会采用tomcat 连接池
@ConditionalOnProperty(
name = {"spring.datasource.type"}, //name用来从application.properties中读取某个属性值
havingValue = "org.apache.tomcat.jdbc.pool.DataSource",
//缺少该property时是否可以加载。如果为true,没有该property也会正常加载;反之报错
// 不管你配不配置 都以 tomcat 连接池作为连接池
matchIfMissing = true //默认是false
)
static class Tomcat {
Tomcat() {
}
//给容器中加数据源
@Bean
@ConfigurationProperties(
prefix = "spring.datasource.tomcat"
)
public org.apache.tomcat.jdbc.pool.DataSource dataSource(DataSourceProperties properties) {
org.apache.tomcat.jdbc.pool.DataSource dataSource = (org.apache.tomcat.jdbc.pool.DataSource)DataSourceConfiguration.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;
}
}
}
如果在类路径没有找到 jar包 则会跑出异常
Field dataSource in com.example.springsession.demo.jpa.StudentController required a bean of type ‘javax.sql.DataSource’ that could not be found.
- Bean method ‘dataSource’ not loaded because @ConditionalOnClass did not find required class ‘org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType’
DataSourceConfiguration
配置文件中没有指定数据源时候 会根据注解判断然后选择相应的实例化数据源对象!
则 type 为空。
@ConditionalOnClass({HikariDataSource.class})
@ConditionalOnMissingBean({DataSource.class}) //注解判断是否执行初始化代码,即如果用户已经创建了bean,则相关的初始化代码不再执行
@ConditionalOnProperty(
name = {"spring.datasource.type"}, //拿配置文件中的type 如果为空返回fale
havingValue = "com.zaxxer.hikari.HikariDataSource", //type 不为空则去 havingValue 对比 ,相同则ture 否则为false
matchIfMissing = true // 不管上面文件中是否配置,默认都进行加载 , matchIfMissing的默值为false
)
static class Hikari {
Hikari() {
}
@Bean
@ConfigurationProperties(
prefix = "spring.datasource.hikari"
)
public HikariDataSource dataSource(DataSourceProperties properties) {
//创建数据源
HikariDataSource dataSource =
(HikariDataSource)DataSourceConfiguration.createDataSource(properties,
//创建数据源
HikariDataSource.class);
if (StringUtils.hasText(properties.getName())) {
dataSource.setPoolName(properties.getName());
}
return dataSource;
}
}
createDataSource 方法
protected static <T> T createDataSource(DataSourceProperties properties, Class<? extends DataSource> type) {
// 使用DataSourceBuilder 建造数据源,利用反射创建type数据源,然后绑定相关属性
return properties.initializeDataSourceBuilder().type(type).build();
}
DataSourceBuilder 类
设置type
public <D extends DataSource> DataSourceBuilder<D> type(Class<D> type) {
this.type = type;
return this;
}
根据设置type的选择类型
private Class<? extends DataSource> getType() {
//如果没有配置type 则为空 默认选择 findType
Class<? extends DataSource> type = this.type != null ? this.type : findType(this.classLoader);
if (type != null) {
return type;
} else {
throw new IllegalStateException("No supported DataSource type found");
}
}
public static Class<? extends DataSource> findType(ClassLoader classLoader) {
String[] var1 = DATA_SOURCE_TYPE_NAMES;
int var2 = var1.length;
int var3 = 0;
while(var3 < var2) {
String name = var1[var3];
try {
return ClassUtils.forName(name, classLoader);
} catch (Exception var6) {
++var3;
}
}
return null;
}
//数组
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"};
使用tomcat 连接池
将
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
若使用MySQL有个默认机制是八个小时空闲连接会自动回收,这个回收是在MySQL的Server端,而Spring Boot 的连接池不知道这个连接已经不可用了,继续用这个连接查询的话就会报错,在配置数据库连接池的时候增加一些检测配置,把一些不可用的连接释放掉。
添加依赖即可
<dependency>
<groupId>org.apache.tomcatgroupId>
<artifactId>tomcat-jdbcartifactId>
<version>8.5.23version>
dependency>
hikari 数据源一些配置:
#spring.datasource.type=com.zaxxer.hikari.HikariDataSource
#spring.datasource.hikari.minimum-idle=5
#spring.datasource.hikari.maximum-pool-size=15
#spring.datasource.hikari.auto-commit=true
#spring.datasource.hikari.idle-timeout=30000
#spring.datasource.hikari.pool-name=DatebookHikariCP
#spring.datasource.hikari.max-lifetime=1800000
#spring.datasource.hikari.connection-timeout=30000
#spring.datasource.hikari.connection-test-query=SELECT 1
一些常用的HiKariCP的配置参数
dataSourceClassName | 这是JDBC驱动程序提供的DataSource类的名称。 请参阅特定JDBC驱动程序的文档以获取此类名.注意不支持XA数据源。 XA需要像bitronix这样的真正的事务管理器。 请注意,如果您使用jdbcUrl进行“old-school”基于DriverManager的JDBC驱动程序配置,则不需要此属性 |
jdbcUrl | 数据库连接url |
username | 用户名 |
password | 密码 |
autoCommit | 自动提交,默认是true |
connectionTimeout | 连接超时时间设置,默认是30s |
idleTimeout | 最大空闲时间,超过最大空闲时间的连接在达到最小空闲连接数 minimumIdle 就不会被回收。默认十分钟 |
minimumIdle | 允许的最小空闲数。当minimumIdl大于等于 maximumPoolSize 时,空闲超时的连接不会被回收。默认是等于 maximumPoolSize |
maximumPoolSize | 最大连接数,默认10 |
connectionTestQuery | 测试连接是否可用的query语句 |
maxLifetime | 最长生命周期,使用中的连接永远不会退役,只有当它关闭时才会被删除。默认30分钟 |
注解说明
@ConditionalOnProperty来控制Configuration是否生效
@ConditionalOnMissingBean({xxxx.class}) //注解判断是否执行初始化代码,即如果用户已经创建了bean,则相关的初始化代码不再执行