<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      SpringBoot項目的spring-boot-maven-plugin插件打包原理

      前言

      在使用SpringBoot的項目中,我們需要配置spring-boot-maven-plugin插件

      <plugin>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-maven-plugin</artifactId>             
      </plugin>
      

      這是SpringBoot自己提供的插件,它可以在maven的生命周期package后重新打包,生成自己的jar包結構。插件提供的功能如下

      核心為repackage,它會在package之后執行,生成一個新的jar包,將之前的jar包命名為 xxx.original。

      打包原理

      生成的xxx.original的jar包結構為

      不包含項目依賴的第三方jar包,MANIFEST.MF文件內容為

      Manifest-Version: 1.0
      Created-By: Maven Archiver 3.4.0
      Build-Jdk-Spec: 11
      Implementation-Title: springbootfirst
      Implementation-Version: 0.0.1-SNAPSHOT
      

      SpringBoot插件生成的jar包結構為

      BOOT-INF/classes 中包含項目所有的class文件,BOOT-INF/lib 下包含項目依賴的第三方jar包,MANIFEST.MF文件內容為

      Manifest-Version: 1.0
      Created-By: Maven Archiver 3.4.0
      Build-Jdk-Spec: 11
      Implementation-Title: springbootfirst
      Implementation-Version: 0.0.1-SNAPSHOT
      Main-Class: org.springframework.boot.loader.JarLauncher
      Start-Class: com.imooc.springbootfirst.SpringbootfirstApplication
      Spring-Boot-Version: 2.1.6.RELEASE
      Spring-Boot-Classes: BOOT-INF/classes/
      Spring-Boot-Lib: BOOT-INF/lib/
      

      插件是如何找到啟動類的

      描述文件中的Start-Class就是我們項目的啟動類,我們可以查看插件源碼來分析

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <version>2.2.1.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-loader</artifactId>
        <version>2.2.1.RELEASE</version>
      </dependency>
      

      先引入插件的maven依賴

      RepackageMojo就是repackage打包要執行的邏輯,核心類為Repackager

      在插件創建MANIFEST.MF文件過程中,如果我們沒有配置MainClass屬性,就會通過MainClassFinder類來查找MainClass

      private static final String SPRING_BOOT_APPLICATION_CLASS_NAME = "org.springframework.boot.autoconfigure.SpringBootApplication";
      
      protected String findMainMethod(JarFile source) throws IOException {
      		return MainClassFinder.findSingleMainClass(source, this.layout.getClassesLocation(),
      				SPRING_BOOT_APPLICATION_CLASS_NAME);
      	}
      

      在所有類中查找包含SpringBootApplication注解且包含main方法的類,并當做啟動類,內部通過ASM字節碼庫來解析class文件得到類信息。

      啟動流程

      java -jar springbootfirst-0.0.1-SNAPSHOT.jar
      

      java啟動jar包會找META-INF/MANIFEST.MF文件中的Main-Class來啟動,SpringBoot插件最終生成的Main-Class為 org.springframework.boot.loader.JarLauncher類。

      /**
       * jar包類型的啟動器
       *
       * @author Phillip Webb
       * @author Andy Wilkinson
       * @since 1.0.0
       */
      public class JarLauncher extends ExecutableArchiveLauncher {
      
      	static final String BOOT_INF_CLASSES = "BOOT-INF/classes/";
      
      	static final String BOOT_INF_LIB = "BOOT-INF/lib/";
      
      	public JarLauncher() {
      	}
      
      	protected JarLauncher(Archive archive) {
      		super(archive);
      	}
      
      	@Override
      	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);
      	}
      
      }
      

      最終運行的是MANIFEST.MF文件中Start-Class,值為com.imooc.springbootfirst.SpringbootfirstApplication,其實就是我們項目中配置的啟動類。

      /**
       * 啟動器
       *
       * @author Phillip Webb
       * @author Dave Syer
       * @since 1.0.0
       */
      public abstract class Launcher {
      
      	/**
      	 * 啟動流程
      	 */
      	protected void launch(String[] args) throws Exception {
      		JarFile.registerUrlProtocolHandler();
      		//根據BOOT-INF/classes下的class文件和BOOT-INF/lib下的第三方jar包創建Archive
      		//創建的ClassLoader為LaunchedURLClassLoader類型
      		ClassLoader classLoader = createClassLoader(getClassPathArchives());
      		launch(args, getMainClass(), classLoader);
      	}
      
      	/**
      	 * 創建新的LaunchedURLClassLoader,從多個URL中加載class
      	 */
      	protected ClassLoader createClassLoader(URL[] urls) throws Exception {
      		return new LaunchedURLClassLoader(urls, getClass().getClassLoader());
      	}
      
      	/**
      	 * 將新的類加載器設置到線程上下文中,并啟動應用程序
      	 */
      	protected void launch(String[] args, String mainClass, ClassLoader classLoader) throws Exception {
      		Thread.currentThread().setContextClassLoader(classLoader);
      		createMainMethodRunner(mainClass, args, classLoader).run();
      	}
      
      	/**
      	 * 創建一個Main方法運行器來啟動應用程序
      	 */
      	protected MainMethodRunner createMainMethodRunner(String mainClass, String[] args, ClassLoader classLoader) {
      		return new MainMethodRunner(mainClass, args);
      	}
      
      }
      

      創建新的ClassLoader類型LaunchedURLClassLoader,從BOOT-INF/classes下和BOOT-INF/lib下的所有jar包中加載class。加載我們整個項目的都是LaunchedURLClassLoader類加載器。

      /**
       * 一個執行Main方法的工具類
       *
       * @author Phillip Webb
       * @author Andy Wilkinson
       * @since 1.0.0
       */
      public class MainMethodRunner {
      
      	private final String mainClassName;
      
      	private final String[] args;
      
      	/**
      	 * Create a new {@link MainMethodRunner} instance.
      	 * @param mainClass the main class
      	 * @param args incoming arguments
      	 */
      	public MainMethodRunner(String mainClass, String[] args) {
      		this.mainClassName = mainClass;
      		this.args = (args != null) ? args.clone() : null;
      	}
      
      	public void run() throws Exception {
      		//使用線程上下文類加載器加載MainClass,就是我們項目中的SpringbootfirstApplication
      		Class<?> mainClass = Thread.currentThread().getContextClassLoader().loadClass(this.mainClassName);
      		//執行Main方法
      		Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
      		mainMethod.invoke(null, new Object[] { this.args });
      	}
      }
      

      參考

      springboot 打包插件spring-boot-maven-plugin打包機制及內部結構分析

      posted @ 2021-11-04 18:50  strongmore  閱讀(8689)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 天堂中文8资源在线8| 婷婷五月综合丁香在线| 精品无码国产日韩制服丝袜| 国产一区二区三区色成人| 一区二区三区四区精品视频| 国内极度色诱视频网站| 国产高清在线精品一区不卡| 国产精品剧情亚洲二区| 亚洲黄色一级片在线观看| 青草成人精品视频在线看| 亚洲av二区三区在线| 丰满无码人妻热妇无码区| 久久久久综合中文字幕| 利津县| 绥芬河市| 国产精品成人久久电影| 摸丰满大乳奶水www免费| 国产睡熟迷奷系列网站| 桐庐县| 婷婷丁香五月亚洲中文字幕| 白嫩少妇无套内谢视频| 护士的小嫩嫩好紧好爽| 欧美 亚洲 另类 丝袜 自拍 动漫| 激情动态图亚洲区域激情| 日韩中文字幕v亚洲中文字幕| 亚洲男人天堂一级黄色片| 99er热精品视频| 国产精品白浆在线观看免费| 国产亚洲精品久久久久久青梅| 亚洲一区二区三级av| 人妻少妇偷人一区二区| 亚洲成av人片无码天堂下载| 国产中文99视频在线观看| 综合偷自拍亚洲乱中文字幕| 久久精品国产99麻豆蜜月| 人妻av无码一区二区三区| 亚洲高清国产成人精品久久| 狠狠色噜噜狠狠狠狠777米奇| 午夜高清福利在线观看| 色婷婷欧美在线播放内射 | 18禁成人免费无码网站|