Home  >  Article  >  Java  >  How to encapsulate the startup entry of SpringBoot application

How to encapsulate the startup entry of SpringBoot application

WBOY
WBOYforward
2023-05-13 10:28:211390browse

How to encapsulate the startup entry of SpringBoot application

Springboot can be said to be a necessary skill for Java programmers. Everyone knows that Springboot can eventually be packaged into a jar package through maven, and then directly use the java -jar command Run a web project (or other). This avoids the complicated operations of the original tomcat-based web project. Springboot can make the deployment of Web services so simple because it has a built-in Jetty (or Tomcat) server, and starts the server during the container startup process to successfully run the Web service.

I believe that all Springbooters will be familiar with the following code. Whether they are new students learning Springboot or new drivers starting to study Springboot source code, this code is almost our starting point. We are so familiar with it that we think it is the starting point of the magical paradise of Springboot. But is it really so?

 @SpringBootApplication
 public class Springboot01helloworldApplication {
     public static void main(String[] args) {
         SpringApplication.run(Springboot01helloworldApplication.class, args);
     }
 }

We all know that after a Java project is packaged, the entry description of the jar package is written in the /META-INF/MANIFEST.MF file. Let us take a look. Contents of this file:

 Manifest-Version: 1.0
 Archiver-Version: Plexus Archiver
 Built-By: MrXu
 Start-Class: com.vivo.internet.nex.repeater.console.RepeaterConsoleApplication
 Spring-Boot-Classes: BOOT-INF/classes/
 Spring-Boot-Lib: BOOT-INF/lib/
 Spring-Boot-Version: 1.5.19.RELEASE
 Created-By: Apache Maven 3.8.1
 Build-Jdk: 1.8.0_281
 Main-Class: org.springframework.boot.loader.JarLauncher

The description of the file entry is the value corresponding to Main-Class, which is org.springframework.boot.loader.JarLauncher. So, next we need to take a look at what exactly this class does?

 // JarLauncher.java
 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() {
     }
     // ...省略无关代码
     public static void main(String[] args) throws Exception {
         (new JarLauncher()).launch(args);
     }
 }

The obvious main function attracts our attention. Yes, this is the entrance. Look at the empty structure of JarLauncher and there is no code. Let’s first look for its parent class:

 // ExecutableArchiveLauncher.java
 public abstract class ExecutableArchiveLauncher extends Launcher {
     public ExecutableArchiveLauncher() {
         try {
             this.archive = this.createArchive();
         } catch (Exception var2) {
             throw new IllegalStateException(var2);
         }
     }
     // ...省略
 }
 
 // Launcher.java
 public abstract class Launcher {
     public Launcher() {}
     // ...省略无关代码
 }

As can be seen from the code, the parent class that actually does the work is ExecutableArchiveLauncher, which constructs an archive instance during initialization, which encapsulates /META-INF/MANIFEST.MF File information. We will also use it later.

Then comes the launch method, we only care about the core execution process:

 // Launcher.java
 protected void launch(String[] args) throws Exception {
     JarFile.registerUrlProtocolHandler();
     ClassLoader classLoader = this.createClassLoader(this.getClassPathArchives());
     this.launch(args, this.getMainClass(), classLoader);
 }
 // ExecutableArchiveLauncher.java
 protected String getMainClass() throws Exception {
     Manifest manifest = this.archive.getManifest();
     String mainClass = null;
     if (manifest != null) {
         mainClass = manifest.getMainAttributes().getValue("Start-Class");
     }
 
     if (mainClass == null) {
         throw new IllegalStateException("No 'Start-Class' manifest entry specified in " + this);
     } else {
         return mainClass;
     }
 }

Here we first call the getMainClass method of the subclass ExecutableArchiveLauncher, the main logic is from /META-INF/MANIFEST. Get the Start-Class information from the MF file, which corresponds to the com.vivo.internet.nex.repeater.console.RepeaterConsoleApplication string, which is associated with the startup class we wrote.

Then comes the specific execution of the launch method. launch() first creates a MainMethodRunner, passes the Start-Class and transparent parameters obtained above, and then calls the run method of MainMethodRunner. The execution of the run method is also very simple, that is, loading the startup class corresponding to Start-Class, and then reflectively calling the main method of the startup class. After that comes the initialization process of the container.

 // Launcher.java
 protected void launch(String[] args, String mainClass, ClassLoader classLoader) throws Exception {
     Thread.currentThread().setContextClassLoader(classLoader);
     // 这里首先调用createMainMethodRunner创建一个MainMethodRunner实例,将mainClass和args参数传入。随后调用
     this.createMainMethodRunner(mainClass, args, classLoader).run();
 }
 protected MainMethodRunner createMainMethodRunner(String mainClass, String[] args, ClassLoader classLoader) {
     return new MainMethodRunner(mainClass, args);
 }
 
 // MainMethodRunner.java
 public MainMethodRunner(String mainClass, String[] args) {
     this.mainClassName = mainClass;
     this.args = args != null ? (String[])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((Object)null, this.args);
 }

The above is the detailed content of How to encapsulate the startup entry of SpringBoot application. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete