SpringBoot中的LaunchedURLClassLoader的作用是什么?

我的公众号:IT周瑜

前几天有一个粉丝朋友问我:SpringBoot中的LaunchedURLClassLoader的作用是什么

今天抽时间给大家来分析分析,当我们在SpringBoot应用中引入spring-boot-maven-plugin后,执行mvn clean package命令,即可将SpringBoot应用打成一个可直接java -jar执行的Jar包,解压该Jar包看看里面的内容: BOOT-INF目录下主要包括classes和lib目录:

classes目录包括应用本身的字节码和配置文件: 而lib目录则包括了应用中第三方依赖

我们再来看MANIFEST.MF文件: 该文件的内容为:

  • 其中Spring-Boot-Classes和Spring-Boot-Lib对应的就是上面介绍的BOOT-INF目录下的classes和lib目录,表示当前应用用到的所有类
  • Start-Class:我们定义的应用启动类,com.zhouyu.MyApplication
  • Main-Class:真正的应用启动类,org.springframework.boot.loader.JarLauncher

基于Java基础知识,当我们运行java -jar hello-spring-boot.jar时,java命令会找Jar包中的MANIFEST.MF文件中指定的Main-Class,并执行它的main()方法,所以大家注意,最开始运行的是JarLauncher中的main()方法,而不是MyApplication中的main()方法,而JarLauncher类就在:

那为什么要多此一举呢?为什么Main-Class不直接为MyApplication呢?我们先看看org.springframework.boot.loader.JarLauncher中main()方法的实现: 在launch()方法中主要分为三步:

  1. 第一步,创建一个ClassLoader,具体类型为LaunchedURLClassLoader
  2. 第二步,找到真正的启动类,最后的getMainClass()取的就是Start-Class的值,也就是MyApplication类
  3. 第三步,会把上面创建的ClassLoader设置为线程上下文类加载器,并运行MyApplication中的main()方法,真正开始启动SpringBoot

也就是说,在执行java -jar hello-spring-boot.jar时,会先创建一个自定义类加载器LaunchedURLClassLoader,并且会成为线程上下文类加载器,然后再运行MyApplication的main()方法,也就是说在运行MyApplication的main()方法时遇到需要加载类时就会用LaunchedURLClassLoader来加载。

那为什么SpringBoot要自定义一个LaunchedURLClassLoader类加载器呢?

因为普通的类加载器只能加载Jar包中直接的类,而不能加载Jar包中的Jar包中的类 ,比如一个普通的Jar包内容为: 普通的类加载器能加载到MyAppliation和ZhouyuController两个类,但是如果这个Jar包中还有一个third.jar包,那么普通的类加载器则没办法加载third.jar中的类了,而SpringBoot想要的效果就是将应用的所有第三方依赖jar全部放在应用的Jar包中,也就是Jar包中包含Jar包,所以需要在启动的最开始自定义一个类加载器,后续就由这个自定义类加载器来加载BOOT-INF目录下的classes目录和lib目录下的类了。

比如hello-spring-boot.jar中就有一个JarFileArchive类,它里面就有一个unpack()方法,自然就是用来解压第三方Jar包并加载其中的类的:

我们也会把SpringBoot插件打出来的Jar叫做FatJar,因为它包含了很多第三方依赖,所以很胖,SpringBoot就像大家的父母,小时候上学,父母会在早上把你一天要用到的东西都准备好放在书包(FatJar)里,你需要时直接从书包里取就可以了,而不用额外再去家里或商店去取了。

我是大都督周瑜,欢迎关注我的公众号:IT周瑜,没有废话,全程干货。

相关推荐
oliveira-time23 分钟前
Java 1.8(也称为Java 8)
java·开发语言
极小狐2 小时前
如何使用极狐GitLab 软件包仓库功能托管 maven?
java·运维·数据库·安全·c#·gitlab·maven
.生产的驴2 小时前
SpringBoot 集成滑块验证码AJ-Captcha行为验证码 Redis分布式 接口限流 防爬虫
java·spring boot·redis·分布式·后端·爬虫·tomcat
野犬寒鸦4 小时前
MySQL索引使用规则详解:从设计到优化的完整指南
java·数据库·后端·sql·mysql
思考的橙子4 小时前
Springboot之会话技术
java·spring boot·后端
钰爱&4 小时前
【Linux】POSIX 线程信号量与互斥锁▲
java·开发语言·jvm
黑匣子~6 小时前
java集成telegram机器人
java·python·机器人·telegram
竹小春逢十八7 小时前
Java常用类概述
java
兆。7 小时前
电子商城后台管理平台-Flask Vue项目开发
前端·vue.js·后端·python·flask
weixin_437398217 小时前
RabbitMQ深入学习
java·分布式·后端·spring·spring cloud·微服务·rabbitmq