SpringBoot jar in jar 加載資源的原理及帶來的問題


使用 IDEA 運行 springboot 程序與 java -jar 運行 springboot 程序時 ClassLoader 不同,導致 classloader.getResource() 拿不到資源

使用 this.getClass().getClassLoader() 獲取 classloader 時,運行方式不同,結果不一樣

使用 IDEA 運行 springboot 程序時,sun.misc.Launcher$AppClassLoader@18b4aac2  
使用 java -jar 運行打包后的 jar 包時,org.springframework.boot.loader.LaunchedURLClassLoader@71dac704
LaunchedURLClassLoader 在以下 jar 包依賴中:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-loader</artifactId>
</dependency>
View Code

 

使用下面的代碼,可以拿到類的代碼的路徑:
如:jar:file:/data/spring-boot-theory.jar!/BOOT-INF/lib/spring-aop-5.0.4.RELEASE.jar!/org/springframework/aop/SpringProxy.class 

ProtectionDomain protectionDomain = getClass().getProtectionDomain();
CodeSource codeSource = protectionDomain.getCodeSource();
URI location = (codeSource == null ? null : codeSource.getLocation().toURI());

對於原始的JarFile URL,只支持一個'!/',SpringBoot 擴展了此協議,使其支持多個'!/',以實現 jar in jar 的加載資源方式。

但是,取到了資源路徑,原生的 new File() 還是處理不了這種資源路徑的。

我們通過傳統的方式取不到資源了,即使取到了,也沒法直接使用,那在 SpringBoot 中我們應該怎么獲取資源呢?
可以參考 MyBatisPlus 中對 xml 文件的處理:com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties#mapperLocations  (有待研究)

 

classloader不同引發的錯誤現象:https://blog.csdn.net/qq_38366063/article/details/97382500
LaunchedURLClassLoader 原理:https://segmentfault.com/a/1190000013532009
spring-boot-load 原理:https://www.jianshu.com/p/bedf5f3a2ad9
springboot classload 的繼承關系和影響:http://hengyunabc.github.io/spring-boot-classloader/

http://hengyunabc.github.io/spring-boot-classloader/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM