使用 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>
使用下面的代码,可以拿到类的代码的路径:
如: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/