正常情况下classloader只能找到jar里面当前目录或者文件类里面的*.class文件。为了能够加载嵌套jar里面的资源之前都是把嵌套jar里面的class文件和应用的class文件打包为一个jar,这样就不存在嵌套jar了,但是这样做就不能很清晰的知道应用到底依赖了哪些东西,哪些是应用自己的,另外多个jar里面的class可能内容不一样但是文件名却一样。springboot中spring-boot-loader就是为优雅解决这个问题而诞生的。
spring-boot-loader模块允许我们使用java -jar archive.jar运行包含嵌套依赖jar的jar或者war文件,它提供了三种类启动器 (JarLauncher, WarLauncher and PropertiesLauncher),这些类启动器的目的一样都是为了能够加载嵌套在jar里面的资源(比如class文件,配置文件等)。[Jar|War]Launcher固定去查找当前jar的lib目录里面的嵌套jar文件里面的资源。
Springboot中jar文件格式固定如下:
archive.jar
|
+-META-INF(1)
| +-MANIFEST.MF
+-org(2)
| +-springframework
| +-boot
| +-loader
| +-<spring boot loader classes>
+-com(3)
| +-mycompany
| + project
| +-YouClasses.class
+-lib(4)
+-dependency1.jar
+-dependency2.jar
那么spring-boot是如何去按照这个结构加载资源那?
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.mycompany.project.MyApplication
并拷贝spring-boot-loader包里面的class文件到结构(2),应用依赖拷贝到(4)应用类拷贝到(3)image.png
注:这里需要思考下为何要拷贝本来应该放入到lib里面的spring-boot-loader.jar里面的class到结构(2)?
image.png
看完这个流程在分析下第三节留的问题,如流程图首先使用Appclassloader加载了JarLauncher类并创建了LaunchedURLClassLoader类,而LaunchedURLClassLoader是属于spring-boot-loader.jar包里面的,而Appclassloader是普通的加载器不能加载嵌套的jar里面的文件,所以如果把spring-boot-loader.jar放到lib 目录下,Appclassloader将找不到LaunchedURLClassLoader。所以在打包时候 拷贝本来应该放入到lib里面的spring-boot-loader.jar里面的class到结构(2)。
spring-boot-load模块通过自定义jar包结构自定义类加载器优雅的实现了嵌套jar资源的加载,通过打包时候重新设置启动类和组织jar结构,通过运行时设置自定义加载器来实现嵌套jar资源加载。更多分析欢迎关注微信公众号‘技术原始积累’
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有