springboot3.5 MySQL 自动装配解析

一、配置环境

1. 配置pom.xml

        <dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency>

2、自动配置图解

 

二、相关代码解析

1、自动配置入口: DataSourceAutoConfiguration

@AutoConfiguration(before = SqlInitializationAutoConfiguration.class)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceCheckpointRestoreConfiguration.class })
public class DataSourceAutoConfiguration {@Configuration(proxyBeanMethods = false)@Conditional(EmbeddedDatabaseCondition.class)@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })@Import(EmbeddedDataSourceConfiguration.class)protected static class EmbeddedDatabaseConfiguration {}//加载条件: 存在DataSource类且未自定义DataSource Bean@Configuration(proxyBeanMethods = false)@Conditional(PooledDataSourceCondition.class)@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })protected static class PooledDataSourceConfiguration {@Bean@ConditionalOnMissingBean(JdbcConnectionDetails.class)PropertiesJdbcConnectionDetails jdbcConnectionDetails(DataSourceProperties properties) {return new PropertiesJdbcConnectionDetails(properties);}}
}

2、驱动类名推导解析:DataSourceProperties#determineDriverClassName

@ConfigurationProperties("spring.datasource")
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {public String determineDriverClassName() {String driverClassName = findDriverClassName();if (!StringUtils.hasText(driverClassName)) {throw new DataSourceBeanCreationException("Failed to determine a suitable driver class", this,this.embeddedDatabaseConnection);}return driverClassName;}String findDriverClassName() {// 根据用户application.properties 里面的配置。 如spring.datasource.driver-class-nameif (StringUtils.hasText(this.driverClassName)) {Assert.state(driverClassIsLoadable(), () -> "Cannot load driver class: " + this.driverClassName);return this.driverClassName;}String driverClassName = null;// 通过application.properties 里面的spring.datasource.url获取if (StringUtils.hasText(this.url)) {driverClassName = DatabaseDriver.fromJdbcUrl(this.url).getDriverClassName();}if (!StringUtils.hasText(driverClassName)) {driverClassName = this.embeddedDatabaseConnection.getDriverClassName();}return driverClassName;}
}

3、驱动名称解析. DatabaseDriver

public enum DatabaseDriver {public static DatabaseDriver fromJdbcUrl(String url) {
// 通过配置的url 解析: url: jdbc:mysql://127.0.0.1:3306/user?useUnicode=true&characterEncoding=utf8if (StringUtils.hasLength(url)) {Assert.isTrue(url.startsWith("jdbc"), "'url' must start with \"jdbc\"");String urlWithoutPrefix = url.substring("jdbc".length()).toLowerCase(Locale.ENGLISH);for (DatabaseDriver driver : values()) {for (String urlPrefix : driver.getUrlPrefixes()) {String prefix = ":" + urlPrefix + ":";if (driver != UNKNOWN && urlWithoutPrefix.startsWith(prefix)) {return driver;}}}}return UNKNOWN;}
}

4、数据源、连接池配置: HikariDataSource

abstract class DataSourceConfiguration {@Configuration(proxyBeanMethods = false)@ConditionalOnClass(HikariDataSource.class)@ConditionalOnMissingBean(DataSource.class)@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource",matchIfMissing = true)static class Hikari {@Beanstatic HikariJdbcConnectionDetailsBeanPostProcessor jdbcConnectionDetailsHikariBeanPostProcessor(ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {return new HikariJdbcConnectionDetailsBeanPostProcessor(connectionDetailsProvider);}@Bean@ConfigurationProperties("spring.datasource.hikari")HikariDataSource dataSource(DataSourceProperties properties, JdbcConnectionDetails connectionDetails,Environment environment) {String dataSourceClassName = environment.getProperty("spring.datasource.hikari.data-source-class-name");HikariDataSource dataSource = createDataSource(connectionDetails, HikariDataSource.class,properties.getClassLoader(), dataSourceClassName == null);if (StringUtils.hasText(properties.getName())) {dataSource.setPoolName(properties.getName());}return dataSource;}}
}

5、驱动加载原理:

JDBC 4.0+ 自动注册机制 (SPI)
  • 驱动JAR中的声明

    MySQL驱动JAR(mysq-connector-j-9.2.0.jar)包含文件:META-INF/services/java.sql.Driver

    内容:com.mysql.cj.jdbc.Driver

  • DriverManager 自动加载

    首次调用DriverManager.getConnection()时,会自动扫描并注册所有META-INF/services下的驱动实现类。

  • DriverManager 的初始化逻辑

  • 代码位置java.sql.DriverManager#getConnection

  • 关键方法:ensureDriversInitialized() 

public class DriverManager {@CallerSensitivepublic static Connection getConnection(String url,java.util.Properties info) throws SQLException {return (getConnection(url, info, Reflection.getCallerClass()));}/** Load the initial JDBC drivers by checking the System property* jdbc.drivers and then use the {@code ServiceLoader} mechanism*/// 通过SPI 加载mysql driver@SuppressWarnings("removal")private static void ensureDriversInitialized() {if (driversInitialized) {return;}synchronized (lockForInitDrivers) {if (driversInitialized) {return;}String drivers;try {drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {public String run() {return System.getProperty(JDBC_DRIVERS_PROPERTY);}});} catch (Exception ex) {drivers = null;}// If the driver is packaged as a Service Provider, load it.// Get all the drivers through the classloader// exposed as a java.sql.Driver.class service.// ServiceLoader.load() replaces the sun.misc.Providers()AccessController.doPrivileged(new PrivilegedAction<Void>() {public Void run() {// SPI 加载DriverServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);Iterator<Driver> driversIterator = loadedDrivers.iterator();/* Load these drivers, so that they can be instantiated.* It may be the case that the driver class may not be there* i.e. there may be a packaged driver with the service class* as implementation of java.sql.Driver but the actual class* may be missing. In that case a java.util.ServiceConfigurationError* will be thrown at runtime by the VM trying to locate* and load the service.** Adding a try catch block to catch those runtime errors* if driver not available in classpath but it's* packaged as service and that service is there in classpath.*/try {while (driversIterator.hasNext()) {driversIterator.next();}} catch (Throwable t) {// Do nothing}return null;}});println("DriverManager.initialize: jdbc.drivers = " + drivers);if (drivers != null && !drivers.isEmpty()) {String[] driversList = drivers.split(":");println("number of Drivers:" + driversList.length);for (String aDriver : driversList) {try {println("DriverManager.Initialize: loading " + aDriver);Class.forName(aDriver, true,ClassLoader.getSystemClassLoader());} catch (Exception ex) {println("DriverManager.Initialize: load failed: " + ex);}}}driversInitialized = true;println("JDBC DriverManager initialized");}}
}
  • 图解:

 

三、总结

1、自动配置:DataSourceAutoConfiguration

2、驱动加载: SPI(机制)

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/913228.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/913228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 Conda 工具链创建 Poetry 本地虚拟环境全记录——基于《Python 多版本与开发环境治理架构设计》

Python 多版本治理理念&#xff08;Windows 平台 零基础友好&#xff09;-CSDN博客 Python 多版本与开发环境治理架构设计-CSDN博客 使用命令行创建项目本地的 Poetry 虚拟环境实战演示 —— 基于《Python 多版本与开发环境治理架构设计》的最佳实践-CSDN博客 一、Python311 环…

北小菜, python , onvif

第一节&#xff1a; 首先是环境的搭建。 环境的搭建。 roottopeet:/home/topeet/source_code/wang_onvif_python# python -m venv venv Command python not found, did you mean:command python3 from deb python3command python from deb python-is-python3 roottopeet:/ho…

TinyWebserver学习(9)-HTTP

一、相关知识 1、有限状态机&#xff1a; 有限状态机&#xff08;Finite State Machine, FSM&#xff09;是一种用于描述对象在其生命周期内可能经历的不同状态及其状态转换规则的模型。它广泛应用于游戏开发、网络协议、词法解析、UI逻辑控制等领域。以下是C中有限状态机的简…

2025最新软件测试面试八股文

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Part1 1、你的测试职业发展是什么&#xff1f; 测试经验越多&#xff0c;测试能力越高。所以我的职业发展是需要时间积累的&#xff0c;一步步向着高级测试工程师…

React 强大的表单验证库formik之集成Yup、React Hook Form库

简介 Formik 是为 React 开发的开源表单库&#xff0c;提供状态管理、验证和提交处理功能&#xff0c;可简化复杂表单的开发。 核心优势 ‌- 状态管理 ‌&#xff1a;自动跟踪输入值、验证状态和提交进度&#xff0c;无需手动编写状态逻辑。 ‌ ‌- 验证功能 ‌&#xff1a;…

破解风电运维“百模大战”困局,机械版ChatGPT诞生?

面对风机87%的非计划停机&#xff0c;30多个专用模型为何束手无策&#xff1f;一套通用大模型如何实现轴承、齿轮、转子“一站式”健康管理&#xff1f;一、行业痛点&#xff1a;风机运维深陷“碎片化泥潭”1.1 87%停机故障由多部件引发齿轮断裂、轴承磨损、电机短路……风电故…

Spring Bean 控制销毁顺序的方法总结

控制Spring Bean销毁顺序的方法 在Spring框架中&#xff0c;有几种方法可以控制Bean的销毁顺序。以下是主要的几种方式及其示例代码&#xff1a; 1. 实现DisposableBean接口 实现DisposableBean接口并重写destroy()方法&#xff0c;Spring会按照依赖关系的相反顺序调用这些方…

Gemini CLI MCP 教程:设置、命令与实际使用

如果你想要为任何 MCP 服务器设置 Gemini CLI,这个快速教程将为你提供指导。 Gemini CLI 结合 MCP(模型上下文协议)服务器,改变了你通过自然语言命令进行编码的方式。 你可以要求 Gemini 分析你的代码库、管理文件、查询数据库,或通过对话提示与 API 交互。 MCP 服务器连…

LangChain 构建向量数据库和检索器

LangChain 构建向量数据库和检索器实战 随着大语言模型&#xff08;LLM&#xff09;在各类 AI 应用中不断普及&#xff0c;RAG&#xff08;Retrieval-Augmented Generation&#xff0c;检索增强生成&#xff09;逐渐成为提升回答准确率与上下文关联性的重要技术路径。 一、什…

基于 LangChain 实现通义千问 + Tavily 搜索 Agent 的简单实践

文章目录 一、相关背景1.1 LangChain 简介1.2 通义千问&#xff08;Tongyi Qianwen&#xff09;1.3 Tavily 实时搜索引擎1.4 架构总览 二、环境配置设置 API 密钥 三、 Tavily 搜索四、智能 Agent 示例&#xff1a;自动判断是否调用 Tavily4.1 初始化 Agent4.2 提问两个问题&am…

SegGPT: 在上下文中分割一切

摘要 我们提出了 SegGPT&#xff0c;一个在上下文中执行“分割一切”的通用模型。我们将各种分割任务统一为一个通用的上下文学习框架&#xff0c;通过将不同类型的分割数据转换为相同的图像格式来兼容这些差异。SegGPT 的训练被建模为一个带有随机颜色映射的上下文着色问题。…

【网络】Linux 内核优化实战 - net.core.busy_read

目录 核心功能工作原理与优势配置方式1. 临时配置&#xff08;重启失效&#xff09;2. 永久配置&#xff08;重启生效&#xff09; 与 net.core.busy_poll 的协同作用适用场景与注意事项适用场景&#xff1a;注意事项&#xff1a; 总结 net.core.busy_read 是 Linux 内核中与网…

alpine安装及配置nodejs开发测试环境

在Alpine Linux上安装和使用Node.js&#xff0c;打造开发和测试的环境。 apk仓库打开社区的源。 先在命令行中使用命令apk search nodejs npm yarn对仓库源进行搜索&#xff0c;&#xff0c;看看nodejs、yarn、npm的版本情况。 localhost:~# apk search nodejs npm yarn nod…

Apache Commons Pool中的GenericObjectPool详解

GenericObjectPool 是 Apache Commons Pool 库中的核心类&#xff0c;用于实现对象的池化管理&#xff0c;适用于数据库连接、HTTP 客户端、线程等昂贵资源的复用。以下从核心概念、工作原理、参数配置、使用场景及最佳实践等方面详细解析&#xff1a; ⚙️ 一、核心概念与组成…

攻防世界CTF题目解析系列————(1)

题目来源:攻防世界wife_wife 打开题目之后&#xff0c;发现登录界面&#xff0c;然后尝试弱口令&#xff0c;sql二次注入&#xff0c;xss发现都没有&#xff0c;然后看见下面go register&#xff08;去注册&#xff09;按钮 成功注册&#xff08;username和password随便搞&…

楚存科技SD NAND贴片式T卡—高性能存储解决方案、赋能AI智能硬件

楚存科技SD NAND贴片式T卡—高性能存储解决方案、赋能AI智能硬件应用 在 AIoT 技术重构产业生态的时代浪潮中&#xff0c;智能硬件正从单一功能终端向数据枢纽演进 —— 智能家居设备日均产生 TB 级交互数据&#xff0c;工业物联网传感器需实时存储生产参数&#xff0c;车载智…

Python[数据结构及算法 --- 查找]

一.顺序查找&#xff08;无序表&#xff09;&#xff1a; def sequentialSearch(alist, item):pos 0found Falsewhile pos < len(alist) and not found:if alist[pos] item:found Trueelse:pos pos 1return foundtestlist [1, 2, 32, 8, 17, 19, 42, 13, 0] print(s…

Seata Saga模式实战:Java微服务中的分布式事务管理

在分布式系统中&#xff0c;Saga模式是一种用于管理跨多个服务的事务的柔性事务解决方案。它通过将长事务拆分为多个本地事务&#xff08;每个事务对应一个服务的操作&#xff09;&#xff0c;并通过补偿机制保证最终一致性。以下是Java中Saga模式的详细介绍&#xff0c;包括实…

若依学习笔记1-validated

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 保证 Spring AOP 相关的依赖包 --><dependency><groupId>org.springframework.boot<…

Excel 如何处理更复杂的嵌套逻辑判断?

处理复杂的嵌套逻辑判断&#xff0c;是Excel进阶路上必然会遇到的一道坎。当简单的IF函数“套娃”变得冗长、难以阅读和维护时&#xff0c;我们就需要更高级、更清晰的工具。 这里介绍三种从基础到高级的处理方法&#xff1a; 传统的 IF 函数嵌套 (经典&#xff0c;但容易混乱)…