当前位置: 首页 > article >正文

Spring Boot 2.1.7 数据源自动加载过程详解

在 Spring Boot 中,数据源的自动配置是框架中一个关键功能,本文将以 Spring Boot 2.1.7 版本为例,详细讲解在单数据源情况下数据源是如何自动加载的。我们通过源码分析,追踪整个加载流程。


1. 自动配置类的发现

Spring Boot 使用 spring.factories 机制加载自动配置类。在 org.springframework.boot.autoconfigure 包的 META-INF/spring.factories 文件中,可以找到:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

其中,DataSourceAutoConfiguration 是数据源的自动配置类。


2. DataSourceAutoConfiguration

进入 DataSourceAutoConfiguration 类,可以看到其内部有一个静态嵌套类 PooledDataSourceConfiguration

@Configuration
@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 {
    protected PooledDataSourceConfiguration() {
    }
}
关键点解释:
  1. @Conditional:依赖于 PooledDataSourceCondition 判断是否满足条件。
  2. @ConditionalOnMissingBean:确保没有自定义DataSourceXADataSource Bean。
  3. @Import:导入了 HikariTomcatDbcp2 等数据源的配置类。

3. DataSourceConfiguration.Hikari

进入 DataSourceConfiguration.Hikari,这是 HikariCP 数据源的配置类(Tomcat、Dbcp2也类似):

@Configuration
@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;
    }
}
关键点解释:
  1. @ConditionalOnClass:确保 HikariDataSource 在类路径中存在,即有在pom文件中直接或间接的导入HikariCP依赖。
  2. @ConditionalOnMissingBean:如果没有自己定义其他 DataSource,则会加载此配置。
  3. @ConditionalOnProperty:当在application.yml或application.properties配置文件中 spring.datasource.type 的值是 HikariDataSource 或未定义时,匹配条件成立,使用 Hikari 数据源。
    @ConditionalOnProperty具体用法可以看这篇:@ConditionalOnProperty

4. createDataSource 方法

进入 DataSourceConfiguration.createDataSource 方法:

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

initializeDataSourceBuilder 方法采用了建造者模式对DataSourceBuilder对象进行了属性赋值。具体源码比较简单,大家可以自己点进去看看,要是看不懂可以先去看看建造者模式的文章。
建造者模式可以看这篇文章:建造者模式


5. DataSourceBuilderbuild 方法

进入build 方法:

public T build() {
    Class<? extends DataSource> type = this.getType();
    DataSource result = (DataSource)BeanUtils.instantiateClass(type);
    this.maybeGetDriverClassName();
    this.bind(result);
    return result;
}
关键步骤:
  1. getType 方法:获取数据源的类型。
  2. BeanUtils.instantiateClass(type):通过反射实例化数据源对象。
  3. bind(result):将配置信息绑定到数据源对象。

6. getType 方法与默认数据源

getType 方法中,当 typenull 时,进入 findType 方法:

private Class<? extends DataSource> getType() {
    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");
    }
}
findType 方法的实现:
public static Class<? extends DataSource> findType(ClassLoader classLoader) {
    String[] var1 = DATA_SOURCE_TYPE_NAMES;
    for (String name : var1) {
        try {
            return ClassUtils.forName(name, classLoader);
        } catch (Exception ignored) {
        }
    }
    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"
};
关键点解释:
  1. 默认数据源顺序

    • com.zaxxer.hikari.HikariDataSource(HikariCP)
    • org.apache.tomcat.jdbc.pool.DataSource(Tomcat 数据源)
    • org.apache.commons.dbcp2.BasicDataSource(DBCP2 数据源)
  2. typenull 时,会按照顺序加载第一个可用的数据源,即 HikariCP


7. 总结

通过以上分析,可以得出 Spring Boot 数据源自动加载的核心流程:

  1. 加载自动配置类:通过 spring.factories 加载 DataSourceAutoConfiguration
  2. 匹配数据源配置:判断条件,导入 HikariTomcatDbcp2 等数据源配置类。
  3. 优先选择 HikariCP:如果未指定 spring.datasource.type,默认会选择 HikariCP 作为数据源。
  4. 数据源初始化:通过 DataSourceBuilder 使用责任链模式构建数据源对象。

8. 源码阅读建议

在阅读 Spring Boot 源码时,版本差异可能会导致配置逻辑有所不同,因此:

  1. 尽量选择与项目中一致的 Spring Boot 版本。
  2. 使用调试工具,逐步跟踪代码执行流程,理解自动配置的细节。

希望本文能帮助大家更好地理解 Spring Boot 2.1.7 数据源自动加载的过程,也欢迎大家在评论区留言,一起交流学习!


http://www.kler.cn/a/445385.html

相关文章:

  • 电源芯片MPQ2179A(TI)
  • 利用爬虫获取的数据能否用于商业分析?
  • 算法-Z-order算法
  • docker(wsl)命令 帮助文档
  • IP协议详解
  • 【Linux】结构化命令:until命令
  • 计算机图形学与虚拟现实(VR):相关学点、图形学、虚拟现实、未来发展
  • 细粒度生物医学多模态对比学习
  • OpenSSL 心脏滴血漏洞(CVE-2014-0160)
  • 番外篇 Git 的原理与使用
  • 【AIGC】结构化的力量:ChatGPT 如何实现高效信息管理
  • 【进阶编程】MVVM的物理架构目录
  • VarifocalLoss在Yolov8中的应用
  • SpringBoot 启动类 SpringApplication 一 构造器方法
  • ESP32物联网开发
  • ChatGPT等大语言模型与水文水资源、水环境领域的深度融合
  • Spring(一)---IOC(控制权反转)
  • Vue.js前端框架教程10:Vue生命周期钩子onBeforeMount 和onMounted
  • ctf文件包含
  • [创业之路-200]:什么是business(业务)?B2B, B2C, B2G业务, 什么是业务设计?
  • 任务一登录安全加固
  • 前端TypeScript学习day03-TS高级类型
  • 任务2 配置防火墙firewalld
  • MySQL——EXPLAIN
  • 深入理解 C++ 中 std::vector 和 std::set 容器的使用
  • 机器学习中做时间序列模型考虑把时间作为特征分析