Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Why can the package packed by Spring Boot run directly?

2025-03-04 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly explains the "Spring Boot package why can run directly", the article explains the content is simple and clear, easy to learn and understand, the following please follow the editor's ideas slowly in depth, together to study and learn "why the Spring Boot package can run directly" it!

Spring Boot provides a plug-in spring-boot-maven-plugin to package the program into an executable jar package.

Just add this plug-in to the pom file:

Org.springframework.boot spring-boot-maven-plugin

The internal structure of the generated executable-jar-1.0-SNAPSHOT.jar after packaging is as follows:

├── META-INF │ ├── MANIFEST.MF │ └── maven │ └── │ └── executable-jar │ ├── pom.properties │ └── pom.xml ├── lib │ ├── aopalliance-1.0.jar │ ├── classmate-1.1.0.jar │ ├── spring-boot-1.3.5.RELEASE.jar │ ├── spring-boot-autoconfigure-1.3.5.RELEASE.jar │ ├──... ├── org │ └── springframework │ └── boot │ └── loader │ ├── ExecutableArchiveLauncher$1.class │ ├──... └ ── spring └── study └── executablejar └── ExecutableJarApplication.class

Then you can directly execute the jar package to start the program:

Java-jar executable-jar-1.0-SNAPSHOT.jar

Several ways to run Spring Boot applications see this article: 3 ways to run Spring Boot applications.

There are 4 file types inside the packaged fat jar:

META-INF folder: program entry, where MANIFEST.MF is used to describe the information of the jar package

Lib directory: places jar packages that third parties depend on, such as some jar packages of springboot

Spring boot loader related code

The code of the module itself

Contents of the MANIFEST.MF file:

Manifest-Version: 1.0 Implementation-Title: executable-jar Implementation-Version: 1.0-SNAPSHOT Archiver-Version: Plexus Archiver Built-By: Format Start-Class: spring.study.executablejar.ExecutableJarApplication Implementation-Vendor-Id: spring.study Spring-Boot-Version: 1.3.5.RELEASE Created-By: Apache Maven 3.2.3 Build-Jdk: 1.8.0_20 Implementation-Vendor: Pivotal Software, Inc. Main-Class: org.springframework.boot.loader.JarLauncher

We see that its Main-Class is org.springframework.boot.loader.JarLauncher, and when we use java-jar to execute the jar package, we call JarLauncher's main method instead of the SpringApplication we wrote.

So what is the purpose of the class JarLauncher?

It is a utility class provided by SpringBoot Loader, a tool provided within SpringBoot, for executing Application classes (fat jar has spring loader-related code inside because it is used here). This is equivalent to SpringBoot Loader providing a set of standards for performing jar packaged by SpringBoot.

Follow Wechat official account: Java technology stack, reply: boot in the background, you can get N Spring boot tutorials that I have sorted out, all of which are practical information.

Some classes abstracted by Spring Boot Loader

Abstract class Launcher: the basic abstract class of various Launcher, used to launch applications; used in conjunction with Archive; there are currently three implementations, JarLauncher, WarLauncher, and PropertiesLauncher.

Archive: the basic abstract class for archiving files. JarFileArchive is the abstraction of jar package files. It provides some methods, such as getUrl will return the Archive corresponding to the URL;getManifest method will get the Manifest data and so on. ExplodedArchive is an abstraction of a file directory

JarFile: for the encapsulation of jar packets, each JarFileArchive corresponds to a JarFile. When JarFile is constructed, it parses the internal structure to get the files or folders in the jar package, which are encapsulated in Entry and stored in JarFileArchive. If Entry is a jar, it will resolve to JarFileArchive.

For example, the URL corresponding to a JarFileArchive is:

Jardisplay filedisplay use UsersformatitoryGitrepositoryGitrepositoryUniGetGitrepositoryUniverse SpringbootMattel analysisUniverse SpringbootMattel executableMutual jarbank target hand executableMustlue jarLay1.0 color SNAPSHOT.jarhorse /

Its corresponding JarFile is:

/ Users/format/Develop/gitrepository/springboot-analysis/springboot-executable-jar/target/executable-jar-1.0-SNAPSHOT.jar

This JarFile has many Entry, such as:

META-INF/ META-INF/MANIFEST.MF spring/ spring/study/.... Spring/study/executablejar/ExecutableJarApplication.class lib/spring-boot-starter-1.3.5.RELEASE.jar lib/spring-boot-1.3.5.RELEASE.jar...

Some of the URL within JarFileArchive depend on the URL corresponding to jar (SpringBoot uses the org.springframework.boot.loader.jar.Handler processor to process these URL):

GitrepositoryGetWord ("analysis");

We see that if there is a jar package that contains jar, or if the jar package contains class files in the jar package, it will be separated by! /, which only org.springframework.boot.loader.jar.Handler can handle, which is an URL protocol extended from within Spring Boot.

The execution process of JarLauncher

The main method of JarLauncher:

Public static void main (String\ [\] args) {/ / construct the JarLauncher and then call its launch method. The parameter is new JarLauncher (). Launch (args) passed by the console;}

The constructor of the parent class ExecutableArchiveLauncher is called when the JarLauncher is constructed.

The constructor of ExecutableArchiveLauncher constructs Archive internally, where JarFileArchive is constructed. In the process of constructing JarFileArchive, a lot of things will be constructed, such as JarFile,Entry.

The launch method of JarLauncher:

Protected void launch (String\ [\] args) {try {/ / registers the custom URL processor: org.springframework.boot.loader.jar.Handler in the system properties. If no processor is specified in URL, the JarFile.registerUrlProtocolHandler () will be queried in the system properties; / / the getClassPathArchives method will find the corresponding third party in the lib directory to rely on JarFileArchive, and the project's own JarFileArchive / / will create the classloader ClassLoader based on the JarFileArchive collection obtained by getClassPathArchives. Here we will construct a LaunchedURLClassLoader classloader, which inherits URLClassLoader and uses the URL of these JarFileArchive collections to construct the parent class loader of URLClassPath / / LaunchedURLClassLoader classloader is the classloader ClassLoader classLoader = createClassLoader (getClassPathArchives ()) that currently executes class JarLauncher; / / the getMainClass method will go to the Manifest in the Archive of the project itself to find the class / call overload method launch launch (args, getMainClass (), classLoader) where key is Start-Class } catch (Exception ex) {ex.printStackTrace (); System.exit (1);} / / getMainClass method of Archive / / find the class spring.study.executablejar.ExecutableJarApplication public String getMainClass () throws Exception {Manifest manifest = 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);} return mainClass;} / / launch overload method protected void launch (String\ [\] args, String mainClass, ClassLoader classLoader) throws Exception {/ / create a MainMethodRunner and pass args and Start-Class to it Runnable runner = createMainMethodRunner (mainClass, args, classLoader) / / construct a new thread Thread runnerThread = new Thread (runner); / / set the class loader and name for the thread, and then start runnerThread.setContextClassLoader (classLoader); runnerThread.setName (Thread.currentThread (). GetName ()); runnerThread.start ();}

The run method of MainMethodRunner:

@ Override public void run () {try {/ / instantiate Class mainClass = Thread.currentThread () .getContextClassLoader () .loadClass (this.mainClassName) according to Start-Class; / / find the main method Method mainMethod = mainClass.getDeclaredMethod ("main", String\ [\] .class) / / if the main method does not exist, throw an exception if (mainMethod = = null) {throw new IllegalStateException (this.mainClassName + "does not have a main method");} / / call mainMethod.invoke (null, new Object\ [\] {this.args});} catch (Exception ex) {UncaughtExceptionHandler handler = Thread.currentThread () .getUncaughtExceptionHandler () If (handler! = null) {handler.uncaughtException (Thread.currentThread (), ex);} throw new RuntimeException (ex);}}

After the main method of Start-Class is called, the Spring container is constructed internally and processes such as the built-in Servlet container are started. We have analyzed all these processes. Spring Boo main class and directory structure introduction, take a look at this article.

About customized classloader LaunchedURLClassLoader

LaunchedURLClassLoader overrides the loadClass method, that is, it modifies the default class loading method (the first to see if this part of the class has been loaded remains the same, and then the rules for actually loading the class have changed, no longer directly from the parent class loader). LaunchedURLClassLoader defines its own class loading rules:

Private Class doLoadClass (String name) throws ClassNotFoundException {/ / 1) Try the root class loader try {if (this.rootClassLoader! = null) {return this.rootClassLoader.loadClass (name);}} catch (Exception ex) {/ / Ignore and continue} / / 2) Try to find locally try {findPackage (name); Class cls = findClass (name); return cls } catch (Exception ex) {/ / Ignore and continue} / / 3) Use standard loading return super.loadClass (name, false);}

Load rules:

If the root class loader exists, call its load method. Here is the root class loading is ExtClassLoader

Call the findClass method of LaunchedURLClassLoader itself, that is, the findClass method of URLClassLoader

Call the loadClass method of the parent class, that is, perform the default class loading order (start with BootstrapClassLoader and look down)

The findClass method of LaunchedURLClassLoader itself:

Protected Class findClass (final String name) throws ClassNotFoundException {try {return AccessController.doPrivileged (new PrivilegedExceptionAction run () throws ClassNotFoundException {/ / parse the class name into a path and add the .class suffix String path = name.replace ('.','/') .class (".class") / / get the URL array based on the previously obtained third-party jar package dependency and your own jar package, and then traverse to find the resource of the corresponding class name / / for example, path is org/springframework/boot/loader/JarLauncher.class. It is found in the jarVera fileGetWord GitrepositoryGitrepositoryhand SpringbootCorp analysisExecutablejarMotObjectAccording to the JarJUBJUBJUT.jarloader Universe 1.3.5.RELEASE.jarpointer / then the URL corresponding to the resource found is the jarrefileholder UsersGitrepositoryDevelopmentGitrepositoryThinSpringboot.executablejarTarget, the executablejartarget, the executablejarsom 1.0, SNAPSHOT.jarmakers / springMushr loader Mueller 1.3.5.RELEASE.jarLauncher.class Resource res = ucp.getResource (JarLauncher.class load) False) If (res! = null) {/ / found the resource try {return defineClass (name, res);} catch (IOException e) {throw new ClassNotFoundException (name, e);}} else {/ / throw ClassNotFoundException exception throw new ClassNotFoundException (name) directly if the resource is not found;}, acc) Catch (java.security.PrivilegedActionException pae) {throw (ClassNotFoundException) pae.getException ();}}

Here is a test of LaunchedURLClassLoader:

/ / register org.springframework.boot.loader.jar.Handler URL protocol processor JarFile.registerUrlProtocolHandler () / / construct the LaunchedURLClassLoader class loader. Here, two URL are used, corresponding to the dependency packages spring-boot-loader and spring-boot in the jar package, separated by "! /". The org.springframework.boot.loader.jar.Handler processor is required to process LaunchedURLClassLoader classLoader = new LaunchedURLClassLoader (new URL\ [\] {new URL) ("org.springframework.boot.loader.jar.Handler processor processing LaunchedURLClassLoader classLoader = UsersUniverse\ [\] {UsersCompact developmentGitrepositoryGitrepositoryGitrepositoryMakeSpringbootRelatisanalysisSpringboothorse executable, Jartarget JarLue 1.0ltel SNAPSHOT.jarlemubject /") New URL ("Jar Velvet fileGel Universe Universe UsersUniverse developer GitrepositoryGitrepositoryGetRepositoryGetWord (") ", LaunchedURLClassLoaderTest.class.getClassLoader ()) / / load classes / / both classes will be found in the second step of local lookup (URLClassLoader's findClass method) classLoader.loadClass ("org.springframework.boot.loader.JarLauncher"); classLoader.loadClass ("org.springframework.boot.SpringApplication"); / / in step 3 classLoader.loadClass ("org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration") will be found in ApplicationClassLoader using the default loading order

The role of Spring Boot Loader

Spring Boot defines its own set of rules in the executable jar package. For example, third parties rely on the jar package in the / lib directory, the URL path of the jar package uses custom rules and this rule needs to be handled by an org.springframework.boot.loader.jar.Handler processor.

Its Main-Class uses JarLauncher, and if it is a war package, it is executed using WarLauncher. Each of these Launcher will have another thread to start the custom SpringApplication class.

These features are packaged through the spring-boot-maven-plugin plug-in.

Thank you for your reading, the above is the "Spring Boot package why can run directly" of the content, after the study of this article, I believe you can directly run the Spring Boot package why this problem has a deeper understanding, the specific use of the situation also needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report