范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

从原理和源码梳理SpringbootFatJar的机制

  一、概述
  SpringBoot FatJar 的设计,打破了标准 jar 的结构,在 jar 包内携带了其所依赖的 jar 包,通过 jar 中的 main 方法创建自己的类加载器,来识别加载运行其不规范的目录下的代码和依赖。二、标准的 jar 包结构
  打开 Java 的 Jar 文件我们经常可以看到文件中包含着一个META-INF目录,这个目录下会有一些文件,其中必有一个MANIFEST.MF,这个文件描述了该 Jar 文件的很多信息 其中 Main-Class 定义 Jar 文件的入口类,该类必须是一个可执行的类,一旦定义了该属性即可通过 java -jar xxx.jar 来运行该 jar 文件。
  在生产环境是使用 java -jar xxx.jar 的方式来运行 SpringBoot 程序。 这种情况下,SpringBoot 应用真实的启动类并不是我们所定义的带有 main 方法的类,而是 JarLauncher 类。查看 SpringBoot 所打成的 FatJar,其 Main-Class 是org.springframework.boot.loader.JarLauncher,这便是微妙之处。Spring-Boot-Version: 2.1.3.RELEASE Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: com.rock.springbootlearn.SpringbootLearnApplication Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Build-Jdk: 1.8.0_131 复制代码
  JAR 包中的 MANIFEST.MF 文件详解以及编写规范三、探索JarLauncher
  org.springframework.boot.loader.JarLauncher这个类是哪里来的呢?答案在 spring-boot-loader-***.jar 包中,可找到这个 JarLauncher 类的源码。在项目中加入 maven 依赖,以便查看源码和远程调试。     org.springframework.boot     spring-boot-loader  复制代码
  认真比较可以看出,这个 spring-boot-loader 包中的内容与 SpringBoot 的 FatJar 包中的一部分内容几乎一样。JarLauncher 在 jar 中的位置如下:
  3.1 只能拷贝出来一份儿
  重点重点重点:因 jar 规范要求 Main-Class 所指定的类必须位于 jar 包的顶层目录下,即 org.springframework.boot.loader.JarLauncher 这个 org 必须位于 jar 包中的第一级目录,不能放置在其他的目录下。所以所以所以只能将 spring-boot-loader 这个 jar 包的内容拷贝出来,而不是整个 jar 直接放置于执行 Jar 中。3.2 携带程序所依赖的jar而非仅class
  上边 JarLauncher 的这个 org.springframework.xx 以及 META-INF 这两个目录是符合 jar 包规范的。但是 BOOT-INF 这个目录里边有点像我们开发中的一些用法:依赖 jar 包在 lib 目录下 但按照 jar 包规范 jar 中不能有 jar 包的情况下程序.class 文件在 classes 目录下 但xxx.class 文件应该按照 org.springframework.xx 这样放置在 jar 中的根目录中
  所以classes 和 lib 你也能意识到,这个设计是独特的。早期 jar 包内携带依赖是采用如 maven-shade-plugin 的做法,把依赖的class文件拷贝到目标 jar 中,但也会造成重名(全限定名)的类会出现覆盖的情况。后来 SpringBoot 为了避免覆盖的情况,修改了打包机制,放弃了maven-shade-plugin那种拷贝class的方式,调整为依赖原始 jar 包;这同时意味着改变了 Jar 标准的运行机制,那么要想让classes和lib中代码能够正常运行,你试想一下如果没有自定义的 classLoader 来加载这些类文件,可以嘛?四、 自定义类加载器的运行机制
  自定义类加载器的常规处理:指定资源指定委托关系指定线程上下文类加载器调用逻辑入口方法4.1 指定资源
  构造方法中基于 jar 包的文件系统信息,构造 Archive 对象public ExecutableArchiveLauncher() { 	this.archive = createArchive(); }  protected final Archive createArchive() throws Exception { 	ProtectionDomain protectionDomain = getClass().getProtectionDomain(); 	CodeSource codeSource = protectionDomain.getCodeSource(); 	URI location = (codeSource != null) ? codeSource.getLocation().toURI() : null; 	String path = (location != null) ? location.getSchemeSpecificPart() : null; 	if (path == null) { 		throw new IllegalStateException("Unable to determine code source archive"); 	} 	File root = new File(path); 	if (!root.exists()) { 		throw new IllegalStateException( 				"Unable to determine code source archive from " + root); 	} 	return (root.isDirectory() ? new ExplodedArchive(root) 			: new JarFileArchive(root)); } 复制代码
  采集 jar 包中的 classes 和 lib 目录下的归档文件。后边创建 ClassLoader 的时候作为参数传入@Override protected List getClassPathArchives() throws Exception { 	List archives = new ArrayList<>( 			this.archive.getNestedArchives(this::isNestedArchive)); 	postProcessClassPathArchives(archives); 	return archives; }  protected boolean isNestedArchive(Archive.Entry entry) { 	if (entry.isDirectory()) { 		return entry.getName().equals(BOOT_INF_CLASSES); 	} 	return entry.getName().startsWith(BOOT_INF_LIB); } 复制代码public static void main(String[] args) throws Exception { 	new JarLauncher().launch(args); } 复制代码4.2 创建自定义 ClassLoaderprotected void launch(String[] args) throws Exception { 	JarFile.registerUrlProtocolHandler();         //创建类加载器, 并指定归档文件 	ClassLoader classLoader = createClassLoader(getClassPathArchives()); 	launch(args, getMainClass(), classLoader); } //创建类加载器, 将归档文件转换为URL protected ClassLoader createClassLoader(List archives) throws Exception { 	List urls = new ArrayList<>(archives.size()); 	for (Archive archive : archives) { 		urls.add(archive.getUrl()); 	} 	return createClassLoader(urls.toArray(new URL[0])); } //父加载器是AppClassLoader protected ClassLoader createClassLoader(URL[] urls) throws Exception {         //getClass().getClassLoader() 是系统类加载器,因为默认情况下main方法所在类是由SystemClassLoader加载的,默认情况下是AppClassLoader. 	return new LaunchedURLClassLoader(urls, getClass().getClassLoader()); }  复制代码4.3 设置线程上下文类加载器,调用程序中的 main classpublic static void main(String[] args) throws Exception { 	new JarLauncher().launch(args); } protected void launch(String[] args, String mainClass, ClassLoader classLoader) 		throws Exception {         //设置线程上下文类加载器 	Thread.currentThread().setContextClassLoader(classLoader); 	//调用MANIFEST.MF 中配置的Start-Class: xxx的main方法,还带入了参数         createMainMethodRunner(mainClass, args, classLoader).run(); } 复制代码

哈勃太空望远镜探测到矮星系的保护罩麦哲伦日冕研究人员证实了难以捉摸的麦哲伦日冕的存在,这是一个由热的电离气体组成的保护性光环,以前只在理论上认为有。几十亿年来,银河系最庞大的宇宙伙伴大麦哲伦云和小麦哲伦云一直在太空中进行着动重阳节老年人饮食谨记四点农历九月初九是我国传统节日重阳节。俗话说家有一老,如有一宝,敬老孝老爱老是中国民族的传统美德。今年的重阳节正好处于国庆假期期间,针对老年人饮食,中国食品科学技术学会日前发布重阳节老政策加力,为制造业高质量发展添动能新华社北京9月30日电题政策加力,为制造业高质量发展添动能新华社记者王雨萧吴雨张辛欣制造业是实体经济的根基。针对市场主体当前困难较大等情况,近日召开的国务院常务会议进一步加大纾困政我国制造业区域高质量发展取得积极成效上半年25个集群完成产值6。2万亿元沿长江11省市已建设1134家绿色工厂,沿黄河9省区工业用水效率高于全国平均水平重点培育的25个先进制造业集群主导产业产值近10万亿元一组组数据折射出我国制造业区域协调发展的可喜变普京的二难俄乌冲突的爆发与延宕,本源是在政治伦理上,国际社会陷入了民族国家与联邦国家的二难。早期斯拉夫人,对古希腊古罗马帝国而言,与盎格鲁萨克逊人日耳曼人一样,同为北方三大蛮族,是奴隶的来源人品有问题的人,微信聊天就知道了01hr聊天是一件很奇妙的事情,黑的可以说成白的,白的可以说成黑的。从古至今,我们都期待一次真诚的聊天,要么给予安慰,要么启迪智慧。战国时的齐闵王,今年去攻打宋国,明年去攻打赵国和一年半内融资三次,红杉腾讯均为股东,这家CRM公司怎么突破内卷?记者李京亚编辑互联网广告圈一位元老级人物杨炯纬进军企业服务赛道,被多方评价为ToB领域的风向标。他所创办的卫瓴科技在投资圈颇有热度,一年半内连续融资三次,红杉腾讯都有站台,最新一轮从代工到合作,李一男的牛创新能源不造车去哪了李一男口中造车没偷过一天懒,也没一天缺过钱的牛创新能源,研发的首款车型自游家NV终于来了。9月29日,自游家品牌官宣,NV将于10月8日全面登场。同时,此前飘忽不定的车辆尾标也最终买学习平板选护眼屏真有必要吗?究竟什么样的学习平板才值得入手学习没兴趣上课听不懂作业不会做家长教不了?等等这些学习问题都是目前家长们所面临的,加上双减政策的实施,没有了辅导班,孩子课堂听讲和课后自学就更加的重要。特别是对于中小学的孩子们,正廿万公里10章新疆餐厅吃饭,有人给片哈密瓜,千万不要接,是笼子哈萨克骑手在北疆勒马驰骋第一节准备一个人到新疆,书记不干了。自从俺在紫鹊界小东江漓江徒步归来之后,觉得一个人独游那是太过瘾了。这不国庆节又要到了放假七天,俺又在发愁到哪里去混过这几新疆怎一个美字了得草原牧区行新疆篇作者光明日报调研组开栏的话清朗的风,从广袤无垠的草原上轻轻拂过,在乳香茶香酒香间盘桓萦绕,又将泥土的芬芳骏马的嘶鸣牧人的歌声送往渺渺的远方草原牧区,是游人向往的大美
别以为用刘海遮住额头就是年轻小伙,7位中年男星扮嫩,个个辣目如今的影视圈,不止大龄女星流行装嫩,就连中年男星也刮起了一阵扮嫩风。为了让中年男星塑造年轻小伙,剧组的造型师大多数会给他们搞一个刘海,企图通过遮住额头来展现年轻小伙的朝气。然而,下江苏省2022年工伤(工亡)赔偿项目及标准工伤保险条例及江苏省实施工伤保险条例办法规定了工伤(工亡)各项待遇及相关标准,具体如下一工伤赔偿项目根据工伤保险条例第五章第3045条详细规定了工伤保险待遇,工伤职工所享受的赔偿项植物界大熊猫宝华玉兰绽放,让人沉醉现代快报讯这两天,随着气温升高,有着植物界大熊猫之称的宝华玉兰在镇江句容宝华山中绽放,繁花满树芳香艳丽,为这个春天增添了一道靓丽的风景。3月3日下午,记者走进江苏句容宝华山半山腰处与中方会晤不到24小时,印度就被曝出,在中印边境部署了大量武器中国外长秦刚在印度新德里参加G20外长会时,会见了作为东道主的印度外长苏杰生。据印媒报道,两国外长只进行大约45分钟的会谈。由于是G20框架下的外交活动,双方讨论了中印在该机制下的中欧基金刘建平积极布局个人养老金业务助力社保金融协同发展中证网讯(记者魏昭宇)伴随个人养老金制度等政策落地,多层次社会保障体系建设持续完善。公募基金行业积极参与个人养老金第三支柱建设,对完善多层次社会保障体系起到重要作用,这也是基金行业深化内涵发展加快高水平研究型大学建设步伐深入学习贯彻党的二十大精神苏州大学党的二十大报告指出,教育科技人才是全面建设社会主义现代化国家的基础性战略性支撑。作为高水平研究型大学,苏州大学把深入学习宣传贯彻党的二十大精神作为委员提出的议案不仅没有掌声,还遭到了骂的声音此文章素材与图片均来源于网络,如有侵权私信联系删除前言一年一度的两届会议将在周末举行。此时,所有的全国人大代表都忙于提出建议和想法。一些全国人大代表提出的建议深深扎根于人民的心中,4月各地电动车新规来了!好坏消息都有,包括免费上牌禁超标车您在阅读文章前可以先点击上方的关注二字,后续将为您带来更多电动车资讯,多谢支持!在新国标出台之后,各地纷纷加强对电动车的管理,每个月几乎都有电动车新规的实施。现在虽然3月才刚刚开始自住购房时代到来,改善型需求机会很好零距离问答No。179提问Questions解答Answers01hryouou你好!想了解一下万科江斓映象府,自己是改善型购房。答江斓映象府位于滨江核心区,是2023年万科映象系立序之作,同时又是前红关注河北春招一调一提助力求职长城网冀云客户端讯(记者刘澜澜周亚彬实习记者王笑秋)又到一年春招季。数据显示,仅2月18日,河北春季首场大型招聘会当天,就有400多家企业参会,提供岗位一万多个,2万人现场求职,多蔚来2022年第四季度营收160。6亿元同比增长62。2中证网讯(记者金一丹)3月1日,蔚来发布2022年第四季度及全年财报,2022年第四季度营收160。6亿元,同比增长62。2,连续11个季度正增长,全年总营收达492。7亿元四季度