SpringBoot加載外部Jar實(shí)現(xiàn)功能按需擴(kuò)展
實(shí)現(xiàn)方案
實(shí)現(xiàn)這個(gè)很簡(jiǎn)單,只需要完成下面兩步:
- 想辦法將 Class 加載到 JVM
- 使 Spring 掃描到 Class
有時(shí)候java中的各種框架以及復(fù)雜的概念源碼給我們?cè)斐闪撕艽罄斫庹系K,特別是Spring家族的所以先想清楚大致實(shí)現(xiàn)步驟比較好
將Class加載到JVM
現(xiàn)在我們?cè)O(shè)定需要加載的 Jar 在 /user/local/java/plugins 目錄下,對(duì)于第 1 步,現(xiàn)在有如下幾種實(shí)現(xiàn)方式:
- 擴(kuò)大
-cp由AppClassLoader幫我們加載外部 Jar - 使用 SpringBoot 提供的啟動(dòng)參數(shù)
loader.path實(shí)現(xiàn) - 自定義
classloader實(shí)現(xiàn)加載指定位置的 Jar
其中 1 和 3 是JDK提供的方案,2是 SpringBoot 擴(kuò)展的方案,畢竟 SpringBoot 也需要自定義加載很多類順帶擴(kuò)展了一個(gè)參數(shù)出來(lái)
方案1
擴(kuò)大 -cp 由 AppClassLoader 幫我們加載外部 Jar
可以使用 classpath 指定類加載的路徑,但 classpath 的生效是有條件的,這里其實(shí)對(duì)應(yīng)了 Jar 包的兩種啟動(dòng)方式:通過(guò)Jar包里的Main函數(shù)啟動(dòng)或者運(yùn)行Jar啟動(dòng)

SpringBoot 打包后 MANIFEST.MF 內(nèi)容如下:
Manifest-Version: 1.0 Created-By: Maven JAR Plugin 3.2.2 Build-Jdk-Spec: 18 Implementation-Title: intelligent-soul Implementation-Version: 0.0.1-SNAPSHOT Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: com.test.MyApplication Spring-Boot-Version: 2.6.15 Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx Spring-Boot-Layers-Index: BOOT-INF/layers.idx
所以需要使用 Main 函數(shù)啟動(dòng)的方式,不能使用之前的常用的 Jar 包啟動(dòng)方式了。對(duì)于 SpringBoot 應(yīng)用 Main-Class 是 JarLauncher 所以此時(shí)啟動(dòng)命令要改成
java -cp /user/local/java/plugins org.springframework.boot.loader.JarLauncher
- 優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單
- 缺點(diǎn):每個(gè) Jar 包啟動(dòng)命令都一樣了,不好區(qū)分
方案2
使用SpringBoot擴(kuò)展的啟動(dòng)參數(shù),使用java -jar 配合Loader.path參數(shù)
因?yàn)?Spring Boot 程序大多是打成 Jar 包,使用 java -jar boot.jar 的方式啟動(dòng) (此時(shí) -cp 無(wú)效),可以使用 loader.path 指定類加載路徑加載其他 Jar,但 loader.path 生效也是有條件的:

SpringBoot 默認(rèn)打包方式的Main-Class是JarLauncher
配置 Main-Class
為了使 loader.path 參數(shù)生效需要生成 Jar 包的 Main-Class 項(xiàng)配置為 PropertiesLauncher,在 maven 中如下配置,可參考 Using the PropertiesLauncher:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 打包時(shí)排除scope為system的包 -->
<includeSystemScope>false</includeSystemScope>
<!-- jvm啟動(dòng)時(shí)通過(guò)-Dloader.path加載包,必須指定layout為ZIP,否則-Dloader.path無(wú)效!??! -->
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<finalName>Test</finalName>
</build>
其中 layout 可配置值如下:
1、JAR,即通常的可執(zhí)行 jar
Main-Class: org.springframework.boot.loader.JarLauncher
2、WAR,即通常的可執(zhí)行war,需要的 servlet 容器依賴位于 WEB-INF/lib-provided
Main-Class: org.springframework.boot.loader.WarLauncher
3、ZIP,即DIR,類似于 JAR
Main-Class: org.springframework.boot.loader.PropertiesLauncher
4、MODULE,將所有的依賴庫(kù)打包(scope為provided的除外),但是不打包 Spring Boot 的任何Launcher
5、NONE,將所有的依賴庫(kù)打包,但是不打包 Spring Boot 的任何 Launcher
無(wú)論啟動(dòng)類是 JarLauncher 或者 PropertiesLauncher,loader.path 引入的 Jar 和 Spring Boot jar 包中 BOOT-INFO/lib 包下 Jar 都是使用類加載器 org.springframework.boot.loader.LaunchedURLClassLoader 進(jìn)行加載,也就是說(shuō)他們使用的是同一個(gè)類加載器。這個(gè)類加載器主要就是負(fù)責(zé)加載 Jar 包里的 Jar 的加載,因?yàn)镴DK沒(méi)有實(shí)現(xiàn)該功能所以 SpringBoot 定義了該類
注意到同一個(gè)程序,打包成不同類型時(shí),PropertiesLauncher (20s) 比 JarLauncher (8s) 啟動(dòng)慢很多。
方案3
自定義類加載器,加載固定目錄下的jar包或者讀取環(huán)境變量路徑
這種方式需要程序啟動(dòng)的某個(gè)節(jié)點(diǎn),調(diào)用自定義類加載器去加載指定目錄下的 Jar 包,時(shí)間點(diǎn)不是很好控制。但這個(gè)定制化程度比較高。
//可以在這里調(diào)用自定義類加載 SpringApplication.run(SpringBootDemo.class, args);
方案4
通過(guò)設(shè)置-Xbootclasspath/a或者 Extention ClassLoader通過(guò)改變參數(shù)java.ext.dirs實(shí)現(xiàn)
會(huì)改變系統(tǒng)類加載器加載行為不安全不推薦?。?!
加載后的類如何掃描進(jìn)入Spring容器
對(duì)于業(yè)務(wù) Jar 包類,可以預(yù)先在SpringBoot中指定好掃描包路徑,那么只需要插件包路徑是com.demo開頭即可,如下
@SpringBootApplication(scanBasePackages = {"com.demo"})
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
如不符合包名前綴一致的情況,需要在jar包META-INF下的spring.factories指定好自動(dòng)裝配的類即可如 mybatis-plus:
# Auto Configure org.springframework.boot.env.EnvironmentPostProcessor=\ com.baomidou.mybatisplus.autoconfigure.SafetyEncryptProcessor org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.baomidou.mybatisplus.autoconfigure.IdentifierGeneratorAutoConfiguration,\ com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration,\ com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration
到此這篇關(guān)于SpringBoot加載外部Jar實(shí)現(xiàn)功能按需擴(kuò)展的文章就介紹到這了,更多相關(guān)SpringBoot加載外部Jar內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot如何使用httpcomponents實(shí)現(xiàn)http請(qǐng)求
這篇文章主要介紹了Spring Boot使用httpcomponents實(shí)現(xiàn)http請(qǐng)求的示例代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
java 實(shí)現(xiàn)下壓棧的操作(能動(dòng)態(tài)調(diào)整數(shù)組大小)
這篇文章主要介紹了java 實(shí)現(xiàn)下壓棧的操作(能動(dòng)態(tài)調(diào)整數(shù)組大小),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02
Java線程本地變量導(dǎo)致的緩存問(wèn)題解決方法
使用緩存可以緩解大流量壓力,顯著提高程序的性能,我們?cè)谑褂镁彺嫦到y(tǒng)時(shí),尤其是大并發(fā)情況下,經(jīng)常會(huì)遇到一些疑難雜癥,這篇文章主要給大家介紹了關(guān)于Java線程本地變量導(dǎo)致的緩存問(wèn)題的解決方法,需要的朋友可以參考下,2024-08-08
手寫簡(jiǎn)版kedis分布式key及value服務(wù)的實(shí)現(xiàn)及配置
這篇文章主要為大家介紹了手寫簡(jiǎn)版的kedis分布式key及value服務(wù)的實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02
Spring boot項(xiàng)目redisTemplate實(shí)現(xiàn)輕量級(jí)消息隊(duì)列的方法
這篇文章主要給大家介紹了關(guān)于Spring boot項(xiàng)目redisTemplate實(shí)現(xiàn)輕量級(jí)消息隊(duì)列的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
SpringBoot使用Kaptcha實(shí)現(xiàn)驗(yàn)證碼的生成與驗(yàn)證功能
這篇文章主要介紹了SpringBoot使用Kaptcha實(shí)現(xiàn)驗(yàn)證碼的生成與驗(yàn)證功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
Java實(shí)現(xiàn)將word轉(zhuǎn)換為html的方法示例【doc與docx格式】
這篇文章主要介紹了Java實(shí)現(xiàn)將word轉(zhuǎn)換為html的方法,結(jié)合實(shí)例形式分析了java針對(duì)doc與docx格式文件的相關(guān)轉(zhuǎn)換操作技巧,需要的朋友可以參考下2019-03-03

