maven springboot 除去指定的jar包_SpringBoot的运行机制
SpringBoot打包机制
先看一眼spring-boot的maven插件打包后的target目录:
其中有一个.jar.original的文件,一个.jar文件,其中.jar.original才是原始的jar包,而.jar文件是经过spring-boot的maven插件处理过后的jar,springboot的maven插件会将原始jar重命名成.jar.original,然后按springboot自己的规范打出一个可执行的jar包。
将该jar包重命名成.zip文件后打开即可看到文件中的内容:
可以看到,springboot执行的jar并不是一个java标准的jar,其中包含了springboot自身定义的内容。我们再打开其中的META-INF/MANIFEST.MF文件,看看其中指定的内容:
Main-Class是其中的启动类,springboot打包出来的jar,启动类并不是工程中包含main方法的启动类,而是springboot自己的JarLauncher类,而工程中定义的启动类在这里变成了Start-Class,由此也可以看出springboot应用在IDE里通过main方法运行与通过java -jar命令运行的区别。
SpringBoot应用的启动
打开springboot的Main-Class JarLauncher类,其中包含main方法:
这是springboot启动的入口,JarLauncher类继承自ExecutableArchiveLauncher类,进入到launch方法可以看到springboot有一个archive的概念,archive是归档的意思,springboot打出来的jar包就是一个archive。
ExecutableArchiveLauncher类的createArchive方法可以看到启动时的archive创建,通过当前类找到jar包的路径,并创建JarFileArchive:
通过getNestedArchives方法可以看到Archive是一个递归的概念,JarFileArchive中可以有其它嵌套的Archive:
在launch方法中,有getClassPathArchives方法的调用,此方法中调用了前面的getNestedArchives方法,传入的Filter是lambda表达式,通过isNestedArchive方法对JarFileArchive中的Entry做过滤:
可以得知,springboot打出的archive jar包中,ROOT-INF/classes/目录被认为是一个嵌套的Archive,ROOT-INF/lib/下的每一个jar包也被认为是一个Archive
因为springboot的archive不是一个标准的jar包,java提供的ClassLoader无法加载到archive中的依赖以及class,springboot提供了新的classloader的实现用来做Archive中类的加载:
可以看到springboot使用的是LaunchedURLClassLoader这个ClassLoader做的类的加载。创建好类加载器后,需要调用Start-Class,即应用中的main方法:
MainMethodRunner.run方法非常简单,逻辑是通过反射调用应用的main:
这一步之后,进入到了应用代码中。
SpringBoot应用初始化
在使用spring boot时,我们在main方法中调用SpringApplication.run进行初始化:
在SpringApplication.run方法中做了Spring的初始化:
可以清晰的看到spring的初始化。创建ApplicationContext对象使用的是createApplicationContext方法,此方法实现如下:
对于非WEB应用,使用的ApplicationContext的实例是DEFAULT_CONTEXT_CLASS,此常用定义为AnnotationConfigApplicationContext类,在依赖注入中提到的这个类,此类用于实现注解配置的ApplicationContext。
回到启动类,启动类上加了一个@SpringBootApplication注解,此注解的定义:
前面Annotation的解析机制中提到,spring能通过解析@ComponentScan注解注册bean,但是springboot中,@ComponentScan标识在SpringBootApplication注解上,AnnotationConfigApplicationContext是定义在spring-context包中的,而@SpringBootApplication是定义在spring-boot-autoconfig中的注解,spring-context包并不依赖于spring-boot-autoconfig包,AnnotationConfigApplicationContext能通过@SpringBootApplication注解完成初始化是因为spring的注解处理工具类能识别出@SpringBootApplication的元注解@ComponentScan以及@AliasFor注解标识 的属性,实现逻辑在spring-core包中的AnnotationConfigUtils类中。
最后看看SpringApplication类的构造器:
在getSpringFactoriesInstances方法中,使用了SpringFactoriesLoader:
打开spring-boot相关的包,能看到spring.factories文件:
SpringFactoriesLoader是spring-core中提供的类,用于处理spring.factories文件,SpringFactoriesLoader.loadFactoryNames方法会读取类路径下的所有META-INF/spring.factories文件:
AutoConfiguration
回到@SpringBootApplication注解的定义:
其注解上被标记了@EnableAutoConfiguration注解,此注解用于实现autoconfiguration。打开此注解可以看到它实际上是使用了注解解析机制中的@Import注解:
如何使用ImportSelector就回到了@Import的处理逻辑中(见前面的文章)。可以看到,实现autoconfiguration的入口正是这个EnableAutoConfigurationImportSelector类,此类的selectImports方法返回的是需要作为配置类的类,这里的具体作用就是拿到类路径下的所有的自动配置的类,其代码实现:
AutoConfigurationMetadataLoader.loadMetadata方法的实现比较简单
即从META-INF/spring-autoconfigure-metadata.properties文件中加载数据,此文件在classpath下可以有多个(每个jar包中都可以有一个),随便打开一个配置文件,看看其中的内容:
里面都是一些配置类。@Import将这些配置类导入给spring的注解处理器ConfigurationClassParser就完成了bean的配置。
另外,在@SpringBootApplication注解上,还标记了一个@ComponentScan注解,其中的excludeFilters中有一个是AutoConfigurationExcludeFilter:
此类会判断如果class标了@Configuration并且此类包含spring.factories文件中,则在处理@Configuration注解时排除此类:
上面的代码中,getAutoConfigurations方法是从SpringFactoriesLoader中取的EnableAutoConfiguration关联的类。
maven springboot 除去指定的jar包_SpringBoot的运行机制相关推荐
- maven springboot 除去指定的jar包_1. Spring Boot概述
1.1 Spring Boot理解 Spring Boot来简化Spring应用开发,约定大于配置,去繁从简,just run就能创建一个独立的,产品级别的应用 背景 J2EE笨重的开发.繁多的配置. ...
- maven springboot 除去指定的jar包_Spring Boot打包瘦身 Docker 使用全过程 动态配置、日志记录配置...
springBoot打包的时候代码和jar包打包在同一个jar包里面,会导致jar包非常庞大,在不能连接内网的时候调试代码,每次只改动了java代码就需要把所有的jar包一起上传,导致传输文件浪费了很 ...
- java生成cmd jar包_Java程序运行机制及cmd编译运行探究(二) cmd编译运行Java程序并打成jar包...
目标:写一个RandomUtils.java工具类,返回一个随机数,并把这个类的字节码文件打成jar包 在Java运行机制及cmd编译运行探究(一)准备工作一文中,我总结了一部分要用到的cmd及编译运 ...
- srtp项目中关于引入Maven仓库中指定版本jar包的一些问题
文章目录 背景 问题 解决方案 打开Maven的搜索 搜索网址打开之后,直接将你想要查找的jar包全名输进去即可,类似于向下面这样. 指定之后仍然代码出错 背景 相信很多和我一样刚入门的新人对于另外一 ...
- springboot基于mybatis扫描jar包中的controller、service、dao、xml
springboot基于mybatis扫描jar包中的controller.service.dao.xml 最近有这样的需求,是将某个业务模块接口,比如新闻的接口模块 作为一个公共固定的模块,整个包括 ...
- java配置pom安装依赖包,Maven pom.xml 添加本地jar包依赖以及打包方法
Maven项目打包时,如果遇到需要添加本地jar包依赖的时候,可以选择两种方法: 1. 安装到本地仓库 第一种方法比较常规,适用于需要添加的jar包也是由maven项目导出,含有pom文件的时候.只需 ...
- IDEA把Springboot打成可执行jar包,内嵌tomcat 这个可以用
IDEA把Springboot打成可执行jar包,内嵌tomcat 2018年11月23日 18:36:30 ta山之石可以攻玉 阅读数 3061 版权声明:本文为博主原创文章,未经博主允许不得转载. ...
- maven导出Java方法_eclipse导出maven工程的可执行jar包
一.eclipse导出maven工程的可执行jar包 建立两个maven工程 ZKServer 和ZKClient 注意:用maven进行开发管理的话,默认的打出来的jar包是不能运行的,需要在pom ...
- maven打包可执行的jar包-包含依赖jar
maven打包可执行的jar包: 1. 首先确保编辑器里maven环境正常 2. 运行打包的jar文件 3. 测试添加依赖后打包. 4. Unable to access jarfile test-m ...
最新文章
- USEARCH11命令大全,200+命令中文简介,快速查找需要功能
- Web.config文件使用
- 汇编-函数调用的理解
- prop和attr在 jquery的
- python爬虫运行不出结果_请问这个为什么就是爬不到,运行之后电脑卡的不行,求大佬指导...
- 你知道哪些情况下不该使用深度学习吗?
- 力扣455. 分发饼干(JavaScript)
- 2016年最酷的十大安全初创公司
- 阿里巴巴(容器镜像服务)docker+springboot实践
- HDU 1863 (图论基础prim算法)
- 创建一个字体wx.Font
- Git教程之如何版本回退
- 学习笔记 - 大数据导论
- Pycharm使用tkinter
- 上地服务器托管机房的现状
- 基于MCR的MATLAB使用案例
- FreeSwitcch(java使用)
- 用友u8文件服务器备份,用友u8 数据备份到云服务器
- mysql格式化去掉千分号_SQL 格式化数字,千分位分隔符并保留2位小数
- 大疆口袋灵眸发布(OSMO Pocket)