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
英文地址,請注明出處:http://en.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;但容易混亂)…