zoukankan      html  css  js  c++  java
  • spring boot jar启动

    spring boot中jar包方式运行主要依赖于,打包后在jar归档文件根目录的org.springfreamwork.boot.loader.JarLauncher类中执行main方法。

    JarLauncher是其中的一个启动引导类,除此以外还有warLauncher,但我们不做过多探讨;

    说说jar启动,首先打包后的jar存在3个目录

    1 boot-info目录,该目录是当前的自己业务代码的核心目录,里面包含class文件夹和lib文件夹,也就是你的项目类加载目录和jar的依赖包目录。

    2 org.springfreamwork.boot.loader文件夹,这个文件夹是jar项目的启动项目;到这里我们意识到了,jar启动并不是直接去启动我们写的项目,而是通过JarLauncher间接启动我们自己的项目。

    3 mate-info目录,这里面有该jar包启动所需要的清单文件,MANIFEST.MF 。

     MANIFEST中有2个配置项最关键。分别是main-class,start-class。main-class的值就是org.springfreamwork.boot.loader.JarLauncher,而start-class才是我们自己项目中定义的静态main方法。

    那么springboot为什么这么设计呢?

    之前我们提到了,jar归档文件中有3个文件夹,那么我们的项目实际在boot-info目录中,如果直接通过java -jar的方式去启动则jar本身的内部文件形式并不是标准的jar包;实际是没法使用的,毕竟jar中包含的文件还存在lib文件夹,而lib中仍然有jar包,这显然不是一个我们常规意义上标准的jar包形式

    所以springboot才使用了,将其最根本的启动项目放在jar归档文件的根目录中也就是,org.springfreamwork.boot.loader这个项目。这样就可以通过java -jar的方式去启动springboot中约定好的项目;当JarLauncher启动后,在使用自定义类加载器去加载我们应用的classes资源和lib资源,从而反射调用我们应用的start-class作为入口方法去启动我们用户的引用。

    protected void launch(String[] args) throws Exception {
            JarFile.registerUrlProtocolHandler();
            ClassLoader classLoader = createClassLoader(getClassPathArchives());
            launch(args, getMainClass(), classLoader);
        }

    上面的代码是启动时的核心代码,创建类加载器,加载资源后反射调用start-class方法。

    protected void launch(String[] args, String mainClass, ClassLoader classLoader) throws Exception {
            Thread.currentThread().setContextClassLoader(classLoader);
            createMainMethodRunner(mainClass, args, classLoader).run();
        }

    而且我们通过launch方法也可以发现,创建类加载器后将类加载器绑定到当前线程,也就是又使用了上下文类加载器,如上面的代码,而下面的代码则是通过上下文类加载器反射静态方法执行用户应用的启动

    public MainMethodRunner(String mainClass, String[] args) {
            this.mainClassName = mainClass;
            this.args = (args != null) ? args.clone() : null;
        }
    
        public void run() throws Exception {
            Class<?> mainClass = Thread.currentThread().getContextClassLoader().loadClass(this.mainClassName);
            Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
            mainMethod.invoke(null, new Object[] { this.args });
        }

     到这里springboot,巧妙的通过start-class和main-class(也就是JarLauncher)将非标准的jar归档文件,变成了可间接执行的项目。而且没有破坏本身的项目结构,可谓是设计的十分巧妙。

  • 相关阅读:
    Matlab 绘制三维立体图(以地质异常体为例)
    Azure DevOps的variable group实现array和hashtable参数的传递
    Azure DevOps 利用rest api设置variable group
    Azure AADSTS7000215 其中一种问题的解决
    Power BI 实现实时更新Streaming Dataset
    AAD Service Principal获取azure user list (Microsoft Graph API)
    Matlab 沿三维任意方向切割CT图的仿真计算
    Azure Powershell script检测登陆并部署ARM Template
    Azure KeyVault设置策略和自动化添加secrets键值对
    Azure登陆的两种常见方式(user 和 service principal登陆)
  • 原文地址:https://www.cnblogs.com/zzq-include/p/13216307.html
Copyright © 2011-2022 走看看