SpringBoot?DataSource数据源实现自动配置流程详解

 更新时间:2022年10月03日 11:02:30   作者:Decade0712  
这篇文章主要介绍了SpringBoot?DataSource数据源实现自动配置流程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

一、重点概念

1、什么是DataSource数据源

javax.sql.DataSource是由JDBC2.0 提供的接口,它负责建立与数据库的连接,当在应用程序中访问数据库时不必编写连接数据库的代码,直接引用DataSource获取数据库的连接对象即可。用于获取操作数据Connection对象

2、数据库连接池

当我们使用数据源建立多个数据库连接,这些数据库连接会保存在数据库连接池中,当需要访问数据库时,只需要从数据库连接池中获取空闲的数据库连接,当程序访问数据库结束时,数据库连接会放回数据库连接池中

二、导入依赖

首先我们需要导入JDBC相关场景

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

然后,我们还需要导入数据库的连接驱动

注意,我们要根据数据库的版本去导入对应版本的驱动

因为Spring Boot它有默认的版本仲裁,即使不声明version也会有默认版本

所以我们可以直接修改依赖引入的版本(maven的就近依赖原则)或者在properties属性中重新声明版本(maven的属性的就近优先原则,下面使用的就是这种方式)

<properties>
	<mysql.version>5.1.49</mysql.version>
</properties>
...
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>${mysql.version}</version>
</dependency>

三、分析自动配置

1、DataSourceAutoConfiguration类

从名字不难看出,这个类和数据源的自动配置有关

@AutoConfiguration(
    before = {SqlInitializationAutoConfiguration.class}
)
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@ConditionalOnMissingBean(
    type = {"io.r2dbc.spi.ConnectionFactory"}
)
@EnableConfigurationProperties({DataSourceProperties.class})
@Import({DataSourcePoolMetadataProvidersConfiguration.class})
public class DataSourceAutoConfiguration {
    public DataSourceAutoConfiguration() {
    }
    ...

通过分析这个自动配置类,我们可以发现它绑定了一个DataSourceProperties.class配置类

@ConfigurationProperties(
    prefix = "spring.datasource"
)
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
    private ClassLoader classLoader;
    private boolean generateUniqueName = true;
    private String name;
    private Class<? extends DataSource> type;
    private String driverClassName;
    private String url;
    private String username;
    private String password;
    private String jndiName;
    private EmbeddedDatabaseConnection embeddedDatabaseConnection;
    private DataSourceProperties.Xa xa = new DataSourceProperties.Xa();
    private String uniqueName;
    ...

我们发现想要修改数据源相关的配置,只需要调整spring.datasource相关配置项即可

这里面有很多数据源的配置项,例如url、username等

在这个自动配置类中还有一个内嵌的配置类PooledDataSourceConfiguration

它在容器中没有DataSource.classXADataSource.class这两种类型的bean时才会生效

它使用@Import导入了针对不同数据库类型数据源连接组件的数据源配置,这些配置仅在使用了相应的数据源连接组件时才生效,一般开发人员只使用其中一种,所以也就只会有一个生效

@Configuration(
    proxyBeanMethods = false
)
@Conditional({DataSourceAutoConfiguration.PooledDataSourceCondition.class})
@ConditionalOnMissingBean({DataSource.class, XADataSource.class})
@Import({Hikari.class, Tomcat.class, Dbcp2.class, OracleUcp.class, Generic.class, DataSourceJmxConfiguration.class})
protected static class PooledDataSourceConfiguration {
    protected PooledDataSourceConfiguration() {
    }
}

我们随便点进一个它导入的数据源连接组件,跳转到DataSourceConfiguration类,可以看到我们前面自动导入的Hikari的相关配置如下,我们梳理一下这个类生效的条件

  • 容器中存在HikariDataSource.class类型的bean
  • 没有DataSource.class这个类型的bean
  • 系统配置项spring.datasource.type的值为com.zaxxer.hikari.HikariDataSource或者空

这里我们介绍一下matchIfMissing:当配置为空时,matchIfMissing为true,配置生效

@Configuration(
    proxyBeanMethods = false
)
@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"
    )
    HikariDataSource dataSource(DataSourceProperties properties) {
        HikariDataSource dataSource = (HikariDataSource)DataSourceConfiguration.createDataSource(properties, HikariDataSource.class);
        if (StringUtils.hasText(properties.getName())) {
            dataSource.setPoolName(properties.getName());
        }
        return dataSource;
    }
}

上述条件满足,所以底层配置好的连接池是:HikariDataSource

2、DataSourceTransactionManagerAutoConfiguration类

事务管理器的自动配置

3、JdbcTemplateAutoConfiguration类

这个是JdbcTemplate的自动配置,JdbcTemplate可以来对数据库进行crud

@AutoConfiguration(
    after = {DataSourceAutoConfiguration.class}
)
@ConditionalOnClass({DataSource.class, JdbcTemplate.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties({JdbcProperties.class})
@Import({DatabaseInitializationDependencyConfigurer.class, JdbcTemplateConfiguration.class, NamedParameterJdbcTemplateConfiguration.class})
public class JdbcTemplateAutoConfiguration {
    public JdbcTemplateAutoConfiguration() {
    }
}

通过分析该自动配置类的配置绑定相关类代码可知,我们可以通过修改spring.jdbc开头的配置来对JdbcTemplate进行配置调整

@ConfigurationProperties(
    prefix = "spring.jdbc"
)
public class JdbcProperties {
    private final JdbcProperties.Template template = new JdbcProperties.Template();
    public JdbcProperties() {
    }
    public JdbcProperties.Template getTemplate() {
        return this.template;
    }

然后这个自动配置类导入的配置类又会去操作我们前面配置好的数据源

也就是下方jdbcTemplate()方法中的dataSource参数

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnMissingBean({JdbcOperations.class})
class JdbcTemplateConfiguration {
    JdbcTemplateConfiguration() {
    }
    @Bean
    @Primary
    JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        Template template = properties.getTemplate();
        jdbcTemplate.setFetchSize(template.getFetchSize());
        jdbcTemplate.setMaxRows(template.getMaxRows());
        if (template.getQueryTimeout() != null) {
            jdbcTemplate.setQueryTimeout((int)template.getQueryTimeout().getSeconds());
        }
        return jdbcTemplate;
    }
}

4、JndiDataSourceAutoConfiguration类

Jndi自动配置

5、XADataSourceAutoConfiguration类

分布式事务的自动配置

四、代码样例

结合上面的源码分析,我们可以写一个简单的demo来进行数据库查询

首先我们去系统配置文件中定义一些关于数据源的配置项

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/decade_test?useUnicode=true&characterEncoding=UTF-8
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver

下面就是测试代码

package com.decade;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
@SpringBootTest
@Slf4j
class SpringbootWebApplicationTests {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Test
    void contextLoads() {
        final Long count = jdbcTemplate.queryForObject("select count(*) from t_decade_user", Long.class);
        log.info("该表中数据总数为{}", count);
    }
}

最后测试结果如图

到此这篇关于SpringBoot DataSource数据源实现自动配置流程详解的文章就介绍到这了,更多相关SpringBoot DataSource数据源配置内容请搜索程序员之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持程序员之家!

相关文章

  • HTTP 415错误-Unsupported media type详解

    HTTP 415错误-Unsupported media type详解

    这篇文章主要介绍了HTTP 415错误-Unsupported media type详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • Spring Boot中使用Actuator的/info端点输出Git版本信息

    Spring Boot中使用Actuator的/info端点输出Git版本信息

    这篇文章主要介绍了Spring Boot中使用Actuator的/info端点输出Git版本信息,需要的朋友可以参考下
    2017-06-06
  • MyBatis中Mapper的注入问题详解

    MyBatis中Mapper的注入问题详解

    这篇文章主要介绍了MyBatis中Mapper的注入问题,我知道在 SpringBoot 体系中,MyBatis 对 Mapper 的注入常见的方式有 2 种,具体哪两种方法跟随小编一起看看吧
    2021-09-09
  • 关于springboot配置druid数据源不生效问题(踩坑记)

    关于springboot配置druid数据源不生效问题(踩坑记)

    今天日常跟着网课学习,学到了整合druid数据源,遇到了好几个坑,希望这篇文章可以帮助一些和我一样踩坑的人
    2021-09-09
  • java中获取类资源的方法总结

    java中获取类资源的方法总结

    在本篇文章里小编给大家整理的是关于java中获取类资源的方法总结,需要的朋友们可以学习参考下。
    2020-02-02
  • SpringCloud 服务注册IP错误的解决

    SpringCloud 服务注册IP错误的解决

    这篇文章主要介绍了SpringCloud 服务注册IP错误的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 使用迭代器Iterator遍历Collection问题

    使用迭代器Iterator遍历Collection问题

    这篇文章主要介绍了使用迭代器Iterator遍历Collection问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • Java实现Redis哨兵的示例代码

    Java实现Redis哨兵的示例代码

    这篇文章主要介绍了Java实现Redis哨兵的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Java线程队列LinkedBlockingQueue的使用

    Java线程队列LinkedBlockingQueue的使用

    本文主要介绍了Java线程队列LinkedBlockingQueue的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • Java?对象深拷贝工具类的实现

    Java?对象深拷贝工具类的实现

    本文主要介绍了Java?对象深拷贝工具类的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07

最新评论

?


http://www.vxiaotou.com