Independent spring application of Springboot

Independent spring application

As mentioned in the title, springboot helps to implement a spring application and independently emphasizes the core position of spring. Why do you say it? Didn't spring use spring in projects before springboot appeared? Quite a few, but in previous projects, whether it is web or non-web project, spring only assumes the role of bonding, some foreigners also jokingly call it "glue". Indeed, in the java EE system, the concepts of IOC and DI were proposed earlier than spring. The birth of spring is actually just a repetitive wheel. After fighting (fighting father), it is important, but not absolute. With the emergence of springboot, spring swept away from its embarrassing position and ushered in a new spring. For example: In the past, web projects used the web container as the core, and the registration and initialization of the spring container were carried out during the startup of the web container. The current spring boot project is based on spring, and the embedding is initialized during the spring startup process. Web container.

FATJAR

It is very simple to start the springboot application. After the packaging is completed, use java -jar xxx.jar to start it. Going around, it looks like you are back to where you started, right? A Main calss is going all over the world. However, this jar is not the other jar, and the jar generated by the springboot application package is still different from the traditional jar.
After packaging with the spring-boot-maven-plugin plug-in, two files are
Package the generated files
generated in the target directory, as shown in the figure: mySpringSecurityTest-1.0-SNAPSHOT.jar (located on the left side of the picture) and mySpringSecurityTest-1.0-SNAPSHOT.jar.original (located on the picture Right).
Root directory
Difference contrast
In fact, by looking at the file directory, you can find that the files in xxx.original include compiled code, static files, and configuration files. There are two more categories in xxx.jar: 1. /org, which is actually dependent on spring boot. Some classes exist in the form of folders; 2. /BOOT-INF/lib, which stores the third-party jar packages that the application depends on. That is to say, the jar packaged by the springboot application is larger than the traditional jar, and the official name is FATJAR.

How to execute FATJAR

Isn't it easy to implement it? It's really simple, java -jar xxx.jar, but its internal implementation principle is worth exploring.
Although there is a difference between FATJAR and ordinary jars, for the java -jar command, it doesn't pay attention to who you are. You only need to know that you are a jar, whether you are fat or ugly, don't pay attention. The Java standard specification defines a series of rules that need to be followed as a jar. One of the most important is the META-INF/MANIFEST.MF file in the jar package, which configures the main class of the program's entry. Take a look at the content of the FATJAR modified file, as shown in the figure: Is
MANIFEST.MF
it strange that the main class is not the Application defined in the program (marked by @SpringBootApplication). Look for it again, and it turned out to be placed under the Start-Class attribute. Sure enough, the startup process of springboot is really not that simple, it really needs to be studied.
It is known that JarLauncher is the entry point of program execution, and the source code is:

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);
	}

}

JarLauncher realization principle

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

Did three things:

  1. Re-register the jar protocol.
    Replace the JDK default protocol sun.net.www.protocol.jar.Handler with org.springframework.boot.loader.jar.Handler. The purpose of replacement is that FATJAR has an extra part of the file (BOOT-INF/lib/ Under the jar package), the new protocol can identify the contents of the jar package and solve the problem of jar in jar. Like /META-INF/spring.factories, third-party dependent classes can also be loaded.
  2. Define the classthpath and create the class loader. The
    core is the isNestedArchive method. The resource files are filtered, and the files under BOOT-INF/lib/ and BOOT-INF/classes/ are filtered out, and the calssloader is created as the classpath
  3. Invoking the overloaded method
    Use the classloader in step 2 to create an Application instance, and call the main method. The core method is SpringbootApplication.run(). I won't do too much research here and leave it for later.

WarLauncher

There is almost no difference between WarLauncher and JarLauncher. The only difference is that the classpath path registered in ClassLoader is different, which can be found by comparing the isNestedArchive method. WEB-INF/classes/, WEB-INF/lib/, WEB-INF/lib-provided are all Belongs to the classpath. The war package packaged by the war method is essentially a FATJAR, so it can also be started by java -jar, and by checking the directory structure of the war package, you can find that the package can also be started by the web container.
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_28411869/article/details/109318439