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/

猜你喜欢

转载自www.cnblogs.com/kevin-yuan/p/13169234.html
jar
今日推荐