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

devtools/2024/12/21 23:07:43/

在 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

java">@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也类似):

java">@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 方法:

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

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


5. DataSourceBuilderbuild 方法

进入build 方法:

java">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 方法:

java">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 方法的实现:
java">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.ppmy.cn/devtools/144204.html

相关文章

自然语言处理的不同流派

基于规则的专家系统&#xff1a; 在早期的NLP研究中&#xff0c;基于规则的方法占据主导地位。这种方法依赖于语言学家和计算机科学家手工编写的一系列规则来指导计算机如何理解和生成语言。这些规则通常基于语言学理论&#xff0c;如乔姆斯基的转换生成语法。优点是系统在规则…

多个Echart遍历生成 / 词图云

echart官网 安装 如果版本报错推荐安装以下版本 npm install echarts4.8.0 --savenpm uninstall echarts//这个是卸载命令以下安装成功后是局部引入:多个Echart遍历生成 vue3echart单个页面多个图表循环渲染展示:<template><div class"main"><div …

作业Day4: 链表函数封装 ; 思维导图

目录 作业&#xff1a;实现链表剩下的操作&#xff1a; 任意位置删除 按位置修改 按值查找返回地址 反转 销毁 运行结果 思维导图 作业&#xff1a;实现链表剩下的操作&#xff1a; 1>任意位置删除 2>按位置修改 3>按值查找返回地址 4>反转 5>销毁 任意…

metagpt中ActionNode的用法

目录 整体流程1. 基础组件&#xff1a;2. SIMPLE_THINK_NODE 和 SIMPLE_CHECK_NODE&#xff1a;3. THINK_NODES 类&#xff1a;4. ThinkAction 类&#xff1a;5. SimplePrint 类&#xff1a;6. Printer 类&#xff1a;7. main 函数&#xff1a;总结&#xff1a;主要执行流程&am…

04、Vue与Ajax

4.1 发送AJAX异步请求的方式 发送AJAX异步请求的常见方式包括&#xff1a; 4.1.1. 原生方式 使用浏览器内置的JS对象XMLHttpRequest const xhr new XMLHttpRequest() xhr.open() xhr.send() xhr.onreadystatechange function(){} 4.1.2. 原生方式 使用浏览器内置的JS函…

基于阿里云日志服务的程序优化策略与实践

背景 我们的服务端程序日志现已全面迁移至阿里云&#xff0c;这一举措极大地便利了我们通过阿里云的日志工具来深入洞察接口的调用状况。 content是个json对象&#xff0c;request和path是content对象下的字段。我的需求是统计每个请求一分钟调用次数。以此为依据考虑优化的方…

RTC实时时钟

BKP&#xff08;备份寄存器&#xff09; 1. 什么是BKP&#xff1f; 备份寄存器是42个16位的寄存器&#xff0c;可用来存储84个字节的用户应用程序数据。他们处在备份域里&#xff0c;当VDD电 源被切断&#xff0c;他们仍然由VBAT维持供电。当系统在待机模式下被唤醒&#xff…

RabbitMQ个人理解与基本使用

目录 一. 作用&#xff1a; 二. RabbitMQ的5中队列模式&#xff1a; 1. 简单模式 2. Work模式 3. 发布/订阅模式 4. 路由模式 5. 主题模式 三. 消息持久化&#xff1a; 消息过期时间 ACK应答 四. 同步接收和异步接收&#xff1a; 应用场景 五. 基本使用 &#xff…