大家好,我是陈老师~大家都知道SpringBoot应用最终会产生一个FatJar,里面包含了所有用到的依赖,启动也很简单,java-jarxxx.jar即可。但是我们公司最后出的包把依赖包移到了外面,然后在启动的时候通过loader.path指定依赖包的位置,比如java-Dloader.path=libs-jarxxxx,也可以启动成功。这样做最大的好处之一就是,如果发现某个依赖有问题,那么我只需要替换掉libs中的一个依赖即可,影响范围可以大大减小。你好奇它是怎么做到的吗?关注公众号:码猿技术专栏,回复关键字:1111获取阿里巴巴内部java性能调优手册的打包方式详解,主要是通过两个maven插件打出这样一个结构化的包。1.spring-boot-maven-plugin这个插件是springboot官方提供的打包插件,主要用于打印fatjar,提供java-jarxxx.jar启动支持。官网地址:https://docs.spring.io/spring....我们需要用到这个插件,因为只有它可以生成支持启动的jar,但是生成的包里面不能没有依赖,什么我们应该做什么?如下图所示:layout:布局方式,这里要选择ZIP,后面会解释原因。includes:选择要包含的依赖项。这里写了一个不存在的jar,所以也是间接实现的,没有进入其他依赖。这种方法很丑陋,但目前还没有找到更合适的解决方案。2.maven-assembly-pluginmaven-assembly-plugin插件可以灵活自定义打包内容,官网地址:https://maven.apache.org/plug....我们现在想用这个插件来提取我们使用的依赖包,应该怎么做呢?现在来看assembly.xml中的关键配置:根据include和exclude属性,可以灵活的通过正则规则将相关依赖解压到指定目录,最后在target中执行mvncleanpackage得到最终的安装包目录:解压安装包:打开libs目录:启动方式分析既然我们已经按照自己想要的结构打包好了,那么启动时如何加载libs目录下的依赖呢?前面说过,springboot插件产生的包是启动的入口。其实springboot会自动在这个包里面打入一个引导类org.springframework.boot.loader.Launcher,它是SpringBoot可执行jar的主要入口。是SpringBootjar文件中的实际Main-Class,它设置了适当的URLClassLoader并最终调用了SpringBoot项目中定义的main()方法。Launcher具有三个子类(JarLauncher、WarLauncher和PropertiesLauncher)。如果我们打包插件的布局配置是ZIP,它会使用PropertiesLauncher。PropertiesLauncher机制说明:PropertiesLauncher默认加载在BOOT-INF/lib/,我们可以通过在loader.properties中设置loader.path或LOADER_PATH环境变量来添加其他加载位置。loader.path:配置以逗号分隔的Classpath类路径,如lib,${HOME}/app/lib,前面的路径优先,类似于javac命令中的-classpath。loader.home:用于解析loader.path配置的相对路径,默认为${user.dir}。因此,打包成功后,我们可以通过java-jar-Dloader.path=xx1,xx2,public
