Spring Boot数据源相关

本文主要介绍

1.  SpringBoot使用数据源配置方式;

2. SpringBoot默认连接池及自动配置原理(HikariCP);

3. SpringBoot替换默认连接池配置方式;

4. SpringBoot整合Druid连接池;

1.  SpringBoot使用数据源配置方式

1.配置数据库驱动(Mysql为例)

<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
</dependency>

2. SpringBoot核心配置文件中配置数据库连接信息

spring.datasource.url=jdbc:mysql:///test_mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456

3. 配置spring-boot-starter-jdbc

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

 2. SpringBoot默认连接池及自动配置原理

SpringBoot 官方提供了三种数据库连接池 HikariCP, Commons DBCP2, Tomcat JDBC Connection Pool

默认使用的连接池是 HikariCP.

1. spring.factories中EnableAutoConfiguration中定义了数据源配置类:

org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration ;

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class })
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.Generic.class,
         DataSourceJmxConfiguration.class })
   protected static class PooledDataSourceConfiguration {
        
   }

   static class PooledDataSourceCondition extends AnyNestedCondition {

      @ConditionalOnProperty(prefix = "spring.datasource", name = "type")
      static class ExplicitType {

      }

      @Conditional(PooledDataSourceAvailableCondition.class)
      static class PooledDataSourceAvailable {

      }

   }

2. DataSourceAutoConfiguration内部类PooledDataSourceConfiguration也是配置类PooledDataSourceConfiguration 中import了 DataSourceConfiguration下的Hikari,Tomcat,Dbcp2,Generic多个内部类

abstract class DataSourceConfiguration {
protected static <T> T createDataSource(DataSourceProperties properties, Class<? extends DataSource> type) { // 使用DataSourceBuilder 建造数据源,利用反射创建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.
 * //2.0 之后默认默认使用 hikari 连接池
 */
@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.
 *  //自定义连接池 接口  spring.datasource.type 配置
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type")
static class Generic {

   @Bean
   DataSource dataSource(DataSourceProperties properties) {
      return properties.initializeDataSourceBuilder().build();
   }

}

3. 在 spring-boot-starter-jdbc 中,默认导入了HikariCP的jar,则DataSourceConfiguration中内部类 Hikari 条件注解生效,会执行

DataSourceConfiguration中的 createDataSource()方法

<artifactId>spring-boot-starter-jdbc</artifactId>
<name>Spring Boot JDBC Starter</name>
<description>Starter for using JDBC with the HikariCP connection pool</description>
<properties>
   <main.basedir>${basedir}/../../..</main.basedir>
</properties>
<scm>
   <url>${git.url}</url>
   <connection>${git.connection}</connection>
   <developerConnection>${git.developerConnection}</developerConnection>
</scm>
<dependencies>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
   </dependency>
   <dependency>
      <groupId>com.zaxxer</groupId>
      <artifactId>HikariCP</artifactId>
   </dependency>
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
   </dependency>
</dependencies>

 4.  createDataSource方法调用了 getType()获取连接池类型;当配置文件中配置了spring.datasource.type 时,就加载配置的数据库连接池类型,如果没有配置就 调用findType(this.classLoader); 从DATA_SOURCE_TYPE_NAMES 中返回第一个类型即: com.zaxxer.hikari.HikariDataSource

 createDataSource(DataSourceProperties properties, Class<? extends DataSource> type) {         return (T) properties.initializeDataSourceBuilder().type(type).build();
        }

DataSourceBuilder{

public T build() {
   Class<? extends DataSource> type = getType();
   DataSource result = BeanUtils.instantiateClass(type);
   maybeGetDriverClassName();
   bind(result);
   return (T) result;
}
private Class<? extends DataSource> getType() {
   //如果没有配置type 则为空 默认选择 findType
   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");
}
public static Class<? extends DataSource> findType(ClassLoader classLoader) {
   for (String name : DATA_SOURCE_TYPE_NAMES) {
      try {
         return (Class<? extends DataSource>) ClassUtils.forName(name, classLoader);
      }
      catch (Exception ex) {
         // Swallow and continue
      }
   }
   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" };

3. SpringBoot替换默认连接池配置方式

1. 改用Commons DBCP2,移除 hikari 依赖引入DBCP2依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-jdbc</artifactId>
   <exclusions>
      <exclusion>
         <groupId>com.zaxxer</groupId>
         <artifactId>HikariCP</artifactId>
      </exclusion>
   </exclusions>
</dependency>
<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-dbcp2</artifactId>
</dependency>

2. 改用Tomcat JDBC Connection Pool 除 hikari 依赖引入tomcat-jdbc依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-jdbc</artifactId>
   <exclusions>
      <exclusion>
         <groupId>com.zaxxer</groupId>
         <artifactId>HikariCP</artifactId>
      </exclusion>
   </exclusions>
</dependency>
<dependency>
   <groupId>org.apache.tomcat</groupId>
   <artifactId>tomcat-jdbc</artifactId>
</dependency>

4. SpringBoot整合Druid连接池

 1. 引入Durid依赖

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid-spring-boot-starter</artifactId>
   <version>1.1.10</version>
</dependency>

2. 增加DataSources配置类 

@Configuration
public class DruidConfig {

   @ConfigurationProperties(prefix = "spring.datasource")
   @Bean
   public DataSource druid() {
      return new DruidDataSource();
   }
}

3.  配置数据源信息

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql:///test_mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
    initialization-mode: always
    # 使用druid数据源
    type: com.alibaba.druid.pool.DruidDataSource
    # 数据源其他配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

4.  引入log4j适配器(springBoot2.0后日志框架不再使用log4j,而是logback)

<dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-log4j12</artifactId>
</dependency>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值