啥?你沒聽過SpringBoot的FatJar?

寫在最前面:

?SpringBoot是目前企業里最流行的框架之一,SpringBoot的部署方式多數采用jar包形式。通常,我們使用java -jar便可以直接運行jar文件。普通的jar只包含當前 jar的信息,當內部依賴第三方jar時,直接運行則會報錯,但是,SpringBoot所打成的jar包,卻可以直接部署運行。今日,小白不黑帶大家來探討一下---SpringBoot的啟動原理。

?通過本篇文章,各位看官可以了解到:

  • ????SpringBoot的啟動過程

  • ? ?SpringBoot的FatJar技術

  • ? ?類加載器的使用

話不多說,開工!

大家都知道,SpringBoot的入口是啟動類的main方法,這是正確的,但也不是完全正確。我們可以簡單了解一下,看看run方法里面做了什么事情。廢話不多說,先上時序圖

再來一張源碼圖!

PS:從時序圖中可以看到,可以通過實現ApplicationRunner/CommandLineRunner方法就可以在SpringBoot啟動完成后,做一些自定義的事情

看到這里,估計大家都會對SpringBoot啟動流程有一個大概的認識。對于更深入的了解,有興趣的小伙伴可以直接看SpringBoot啟動類源碼。

好的,收工,下班!

你以為這樣就結束了?No!NoNo,這并不是我今天所要講的,讓我們把維度再往上拉一層,我們的SpringBoot項目的main方法是如何被執行的?

?眾所周知,我們的SpringBoot項目都是通過java -jar運行的,不知道大家是否想過一個問題,java -jar就可以運行整個SpringBoot應用,那么,該項目依賴的jar包是如何被加載的呢?

這就涉及到SpringBoot的FatJar設計了。所謂FatJar,其實就是SpringBoot的一個jar包。對于SpringBoot的可運行jar包,其實是包含了項目所有依賴的,這種打包方式歸功于SpringBoot的一個打包插件spring-boot-maven-plugin。這玩意就相當于是一個攔截器,在maven package后,將maven 打成的jar包變成fatJar,并保留原來的jar包為xx.original。各位看官,請看圖!

PS:spring-boot-maven-plugin需要引入spring-boot-starter-parent才會生成fatjar(實踐出真知)

好了,講了那么久fatjar,那么,FarJar究竟長啥樣呢?各位看官,請再看圖

PS:BOOT-INF:存放業務代碼以及相關的依賴jar包META-INF:這個文件極其重要,里面存放了SpringBoot項目的元信息,包括主類信息,依賴信息,類路徑信息等
org.springframework.boot.loader:SpringBoot自帶的代碼,用來啟動springboot項目,調用我們業務代碼中的main方法

ok,現在讓我們來分析一下META-INF這個文件幾個重要的信息

  • ?Implementation-Ttitle:項目名稱

  • Main-Class:SpringBoot程序真正的啟動類

  • Start-Class:平時業務代碼中的啟動類

  • Spring-Boot-Lib:依賴的jar包路徑

SpringBoot通過Meta-INF清單文件,就可以解析到整個SpringBoot項目的信息,便可以找到對應的入口程序,啟動SpringBoot項目。

來到這里,我們再思考一下,對于java -jar命令,只會執行主類的main方法。讓我們看看這個main方法,是如何啟動springBoot項目的。

首先,看到JarLuncher()有個main方法,該方法創建了一個JarLauncher實例,并調用其launch方法,讓我們點進去一探究竟

?可以看到,launch()方法,先是創建了一個類加載器,然后獲取主類,實際拿的是META-INF下的start-class,再調用重載方法launch(),執行start-class。而這個類加載器,就是LaunchedURLClassLoader。該類加載器可以加載指定路徑下的類,如lib文件夾的jar包。

?讓我們再看看重載方法lunch()方法的實現,該實現首先將LaunchedURLClassLoader設置為線程的上下文類加載器,然后調用createMainMethodRunner方法。

由此可以分析出,SpringBoot的加載,是打破了雙親委派機制的。因為ThreadContextClassLoader的存在,就是為了打破雙親委派機制。

那么,問題來了,ThreadContextClassLoader是如何打破雙親委派的呢?

只需要在被父ClassLoader加載的類中,使用ContextClassLoader去加載其無法加載的類即可。另外,創建線程的時候,設置一下當前線程的ContextClassLoader便可。而普通線程池里面,默認的線程工廠在創建線程時,會默認繼承父線程的線程上下文類加載器。

PS:之所以要打破雙親委派,原因之一是需要底層的類加載器,委托上層的類加載器去加載自定義的類。

讓我們來看看createMainMethodRunner的最終實現。

?首先,該方法通過類加載器Class.forName將啟動類(Start-class)加載進內存,然后通過反射,調用其main方法。也就是最終我們業務代碼中的main方法。

至此,SpringBoot便從業務代碼的啟動類開啟,初始化各種組件,完成SpringBoot的啟動流程。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/42037.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/42037.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/42037.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

robotframework-appiumLibrary 應用 - 實現 app 自動化

1、安裝appiumLibrary第三方庫 運行pip命令:pip install robotframework-appiumlibrary 若已安裝,需要更新版本可以用命令:pip install -U robotframework-appiumlibrary 2、安裝app自動化環境。 參考我的另外一篇專門app自動化環境安裝的…

設計模式探索:策略模式

1. 什么是策略模式(Strategy Pattern) 定義 策略模式(Strategy Pattern)的原始定義是:定義一系列算法,將每一個算法封裝起來,并使它們可以相互替換。策略模式讓算法可以獨立于使用它的客戶端而…

打卡第4天----鏈表

通過學習基礎,發現我的基本功還得需要再練練,思路得再更加清晰明了,這樣子做算法題才能駕輕就熟。每天記錄自己的進步。 一、兩兩交換 題目編號:24 題目描述: 給你一個鏈表,兩兩交換其中相鄰的節點,并返回交換后鏈表的頭節點。你必須在不修改節點內部的值的情況下完成本…

[數據結構] 基于交換的排序 冒泡排序快速排序

標題:[數據結構] 基于交換的排序 冒泡排序&&快速排序 水墨不寫bug (圖片來源于網絡) 目錄 (一)冒泡排序 優化后實現: (二)快速排序 I、實現方法: &#…

opencv環境搭建-python

最近遇到了一些圖像處理的需求,所以需要學習一下opencv,來記錄一下我的學習歷程。 安裝numpy pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy安裝matplotlib pip install -i https://pypi.tuna.tsinghua.edu.cn/simple matplotlib安裝opencv …

ctfshow web入門 web338--web344

web338 原型鏈污染 comman.js module.exports {copy:copy };function copy(object1, object2){for (let key in object2) {if (key in object2 && key in object1) {copy(object1[key], object2[key])} else {object1[key] object2[key]}}}login.js var express …

【ubuntu】掛載新磁盤

1、查看磁盤 sudo fdisk -l#Disk /dev/sdb: 4.0 TiB #Disk model: HNA641010BCF105 #Units: sectors of 1 * 512 512 bytes #Sector size (logical/physical): 512 bytes / 4096 bytes #I/O size (minimum/optimal): 4096 bytes / 4096 bytes #Disklabel type: gpt #Disk id…

python argparse模塊nargs用法

nargs 是 argparse 模塊中用來指定參數的數量的屬性。不同的 nargs 取值有不同的含義,下面是一些常用的用法: nargsNone (默認值):表示該參數只能接收一個值。例如:--foo 123。 nargs?:表示該參數最多接收一個值。如…

gcc/g++的四步編譯

目錄 前言1.預處理(進行宏替換)2.編譯(生成匯編)3.匯編(生成二進制文件)4. 鏈接 (生成可執行文件)a. 動態庫 && 動態鏈接b. 靜態庫 && 靜態鏈接c. 驗證d. 動靜態鏈接…

技術實現路徑怎么寫?(Word項目技術路徑文檔參考)

軟件項目編寫技術實現路徑至關重要,因為它為項目團隊提供了清晰的開發藍圖。這一路徑明確了從項目啟動到交付各階段所需的技術方案、步驟及預期成果,有助于團隊統一認識,確保開發工作有序進行。同時,技術實現路徑有助于識別潛在的…

HetuEngine簡介

目錄 HetuEngine是什么? HetuEngine的特點以及使用場景 特點 使用場景 HetuEngine介紹 結構 近期用到了Hetu,了解下這個工具是起什么作用的。 HetuEngine是什么? 是引擎,設計是為了讓與當前的大數據生態完美融合的引擎&am…

本安防爆手機:危險環境下的安全通信解決方案

在石油化工、煤礦、天然氣等危險環境中,通信安全是保障工作人員生命安全和生產順利進行的關鍵。防爆智能手機作為專為這些環境設計的通信工具,提供了全方位的安全通信解決方案。 防爆設計與材料: 防爆智能手機采用特殊的防爆結構和材料&…

Mysql部署MHA高可用

部署前準備: mysql-8.0.27下載地址:https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.27-1.el7.x86_64.rpm-bundle.tar mha-manager下載地址:https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-mana…

【Selenium】 使用save_screenshot截圖無法保存圖片

Selenium 使用save_screenshot截圖無法保存 代碼如下 from time import sleep from selenium import webdriver driver webdriver.Chrome() driver.maximize_window() driver.get(http://www.baidu.com) # 截取當前窗口,指定截圖圖片的保存位置 driver.save_scre…

為什么需要做網絡安全服務?

網絡安全服務之所以重要,是因為它在保護數字資產、維護企業運營、確保法規遵從、防范惡意行為以及建立信任等方面扮演著關鍵角色。以下是一些主要的理由: 保護核心資產和數據: 數字化轉型使得企業數據變得極其寶貴,包括知識產權、…

深度學習模型加密python版本

支持加密的模型: # torch、torch script、onnx、tensorrt 、torch2trt、tensorflow、tensorflow2tensorrt、paddlepaddle、paddle2tensorrt 深度學習推理模型通常以文件的形式進行保存,相應的推理引擎通過讀取模型文件并反序列化即可進行推理過程. 這樣一來&#…

數據庫——事務管理

title: 數據庫——事務管理 date: 2024-07-06 11:55:39 tags: 數據庫 categories: 數據庫 cover: /image/T1.jpg description: 數據庫的事務管理的相關知識 事務管理 事務管理是對一系列數據庫操作進行管理的過程,這些操作被視為一個不可分割的工作單元&#xff0…

20K Stars!一個輕量級的 JS 庫

大家好,我是CodeQi! 一位熱衷于技術分享的碼仔。 Driver.js 是一個輕量級的 JavaScript 庫,旨在幫助開發人員創建網站或應用程序的引導和教程。通過 Driver.js,您可以引導用戶了解網站的各個功能和使用方式。 Driver.js 提供了高度可定制的功能,使其能夠適應各種需求和…

寶塔-Linux模板常用命令-centos7

一、寶塔-Linux模板常用命令: 1.停止寶塔 /etc/init.d/bt stop 2.啟動寶塔 /etc/init.d/bt start 3.重啟寶塔 /etc/init.d/bt restart 4.卸載寶塔 /etc/init.d/bt stop && chkconfig --del bt && rm -f /etc/init.d/bt && rm -rf …

如何使用echart做K線圖

使用ECharts制作K線圖需要先引入ECharts的庫文件&#xff0c;然后通過調用相應的API來配置和渲染K線圖。以下是一個簡單的示例代碼&#xff1a; // 引入ECharts庫文件 <script src"https://cdn.jsdelivr.net/npm/echarts5.0.0/dist/echarts.min.js"></scri…