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

[SpringBoot] in-depth and simple analysis of the application type identification mechanism of SpringBoot

2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

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

WeChat account: GitShare

Official account of Wechat: a straw that loves to toss.

If you have any questions or suggestions, please leave a message on the official account [1]

Previous continuation

In order to help the majority of SpringBoot users to "know what it is, but also need to know why", the author will deeply analyze the SpringBoot2.0.0.RELEASE version through a series of SpringBoot articles, so that you can have a deep understanding of its internal working principle.

1. [SpringBoot] use SpringBoot to quickly build and start the project

2. [SpringBoot] explain the startup process of SpringBoot application in detail

Infer the type of application

When SpringBoot starts, when creating a SpringApplication object, it automatically identifies and sets whether the current application is an ordinary web application, a responsive web application or a non-web application. What is the internal implementation principle?

First, look at the source code.

/ * *

* infer the type of application

, /

Private WebApplicationType deduceWebApplicationType () {

If (ClassUtils.isPresent (REACTIVE_WEB_ENVIRONMENT_CLASS, null)

&! ClassUtils.isPresent (MVC_WEB_ENVIRONMENT_CLASS, null)) {

Return WebApplicationType.REACTIVE

}

For (String className: WEB_ENVIRONMENT_CLASSES) {

If (! ClassUtils.isPresent (className, null)) {

Return WebApplicationType.NONE

}

}

Return WebApplicationType.SERVLET

}

ClassUtils.isPresent () method:

Its function is to determine whether the class with the provided class name exists and can be loaded. The source code is as follows:

Public static boolean isPresent (String className, @ Nullable ClassLoader classLoader) {

Try {

ForName (className, classLoader)

Return true

}

Catch (Throwable ex) {

/ / Class or one of its dependencies is not present...

Return false

}

}

The forName () method is called, and if an exception occurs, false is returned, which means that the target class does not exist.

Source code analysis of the forName () method:

Public static Class forName (String name, @ Nullable ClassLoader classLoader)

Throws ClassNotFoundException, LinkageError {

Assert.notNull (name, "Name must not be null")

/ / resolves the given class name name to a wrapper class of the base type according to the JVM naming convention of the base class (if appropriate)

Class clazz = resolvePrimitiveClassName (name)

If (clazz = = null) {

/ / commonClassCache is a Map collection that contains all the classes under the java.lang package, with the class name as the key and the corresponding class as the value.

Clazz = commonClassCache.get (name); / / gets the value in the commonClassCache collection based on the class name. If it is empty, the target class is not a subclass of the java.lang package, that is, it is not the original type.

}

If (clazz! = null) {

/ / if the class has been obtained according to the class name, the class is returned directly.

Return clazz

}

/ / determine whether the clas attribute value is an array object. For example: java.lang.String []

/ / "java.lang.String []" style arrays

If (name.endsWith (ARRAY_SUFFIX)) {

/ / if so, truncate the "[]" square brackets after the class name, return java.lang.String, find the class name recursively, and convert the Class type to an array.

String elementClassName = name.substring (0, name.length ()-ARRAY_SUFFIX.length ())

Class elementClass = forName (elementClassName, classLoader)

Return Array.newInstance (elementClass, 0). GetClass ()

}

Whether the / / class property value is a binary representation of an array object. For example: [Ljava.lang.String

/ / "[Ljava.lang.String;" style arrays

If (name.startsWith (NON_PRIMITIVE_ARRAY_PREFIX) & & name.endsWith (";")) {

/ / if so, truncate the "[L" part of the value, find the class name recursively, and convert the corresponding Class type to an array

String elementName = name.substring (NON_PRIMITIVE_ARRAY_PREFIX.length (), name.length ()-1)

Class elementClass = forName (elementName, classLoader)

Return Array.newInstance (elementClass, 0). GetClass ()

}

/ / whether the class attribute value is a two-dimensional array

/ / "[I" or "[[Ljava.lang.String;" style arrays]

If (name.startsWith (INTERNAL_ARRAY_PREFIX)) {

String elementName = name.substring (INTERNAL_ARRAY_PREFIX.length ())

Class elementClass = forName (elementName, classLoader)

Return Array.newInstance (elementClass, 0). GetClass ()

}

/ / obtain classLoader

ClassLoader clToUse = classLoader

If (clToUse = = null) {

/ / if classLoader is empty, the default classLoader object is obtained.

ClToUse = getDefaultClassLoader ()

}

Try {

/ / return the loaded class

Return (clToUse! = null? ClToUse.loadClass (name): Class.forName (name))

}

Catch (ClassNotFoundException ex) {

/ / used to handle the case of inner classes.

Int lastDotIndex = name.lastIndexOf (PACKAGE_SEPARATOR)

If (lastDotIndex! =-1) {

/ / concatenate the name of the inner class.

String innerClassName = name.substring (0, lastDotIndex) + INNER_CLASS_SEPARATOR + name.substring (lastDotIndex + 1)

Try {

Return (clToUse! = null? ClToUse.loadClass (innerClassName): Class.forName (innerClassName))

}

Catch (ClassNotFoundException ex2) {

/ / Swallow-let original exception get through

}

}

Throw ex

}

}

Let's take a look at the constant values used:

REACTIVE_WEB_ENVIRONMENT_CLASS:org.springframework.web.reactive.DispatcherHandler

MVC_WEB_ENVIRONMENT_CLASS:org.springframework.web.servlet.DispatcherServlet

WEB_ENVIRONMENT_CLASSES: {"javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"}

That is to say,

1. If the class org.springframework.web.reactive.DispatcherHandler exists in the application, it means that it is a responsive web application. When the project is started, it needs to go to

Load and start the embedded responsive web server.

2. If neither the javax.servlet.Servlet class nor the org.springframework.web.context.ConfigurableWebApplicationContext class exists in the application, the

Indicates that the current application is not a web application, and there is no need to load the startup embedded web server at startup.

3. Except for the above two cases, it means that the current application is a servlet web application, and you need to load the web server (such as Tomcat) that starts the embedded servlet.

Infer and set the definition class (startup class) of the main method

When SpringBoot starts, when you create a SpringApplication object, you will finally infer and set the definition class (startup class) of the main method. What is the principle of its implementation?

Take a look at the source code first

Private Class deduceMainApplicationClass () {

Try {

StackTraceElement [] stackTrace = new RuntimeException () .getStackTrace

For (StackTraceElement stackTraceElement: stackTrace) {

If ("main" .equals (stackTraceElement.getMethodName () {

Return Class.forName (stackTraceElement.getClassName ())

}

}

}

Catch (ClassNotFoundException ex) {

/ / Swallow and continue

}

Return null

}

What is java.lang.StackTraceElement?

The class element represents a stack frame. All stack frames except one at the top of the stack represent a method call. The frame at the top of the stack represents the execution point at which the stack trace is generated.

StackTraceElement.getMethodName () returns the name of a method that contains the execution point represented by the stack trace element.

StackTraceElement.getClassName () returns a fully qualified name that contains the execution point class represented by the stack trace element.

What is the purpose of java.lang.Class.forName ()?

The java.lang.Class.forName (String name, boolean initialize, ClassLoader loader) method returns the Class object of the class or interface with the given string name, using the given class loader.

Parameter description

-name: this is the fully qualified name of the desired class.

-initialize: this indicates whether this class must be initialized.

-loader: this is the class loader for the class that must be loaded.

Exception description

-LinkageError: if linkage fails.

-ExceptionInInitializerError: if initialization caused by this method fails.

-ClassNotFoundException: if the class cannot be located in the classloader specified by.

Parameter usage

-ClassLoader loader: if the parameter loader loader is empty, load the class through the bootstrap classloader.

-boolean initialize: if it is not initialized, the initialize parameter is true.

Through the explanation of the above knowledge points, the role of deduceMainApplicationClass is very clear, mainly to get the current method call stack, traverse the call stack information to find the class of the main function, and return this class.

Summary

1. SpringBoot checks whether there is an org.springframework.web.reactive.DispatcherHandler class in classpath by calling the isPresent method of the ClassUtils class.

Javax.servlet.Servlet class and org.springframework.web.context.ConfigurableWebApplicationContext class to determine whether the current application is a responsive Web application, an ordinary Servlet Web application, or a non-Web application.

2. SpringBoot determines the class of the current main function by obtaining the call stack information of the current method.

Postscript

In order to help the majority of SpringBoot users to "know what it is, but also need to know why", the author will deeply analyze the SpringBoot2.0.0.RELEASE version through a series of SpringBoot articles, so that you can have a deep understanding of its internal working principle.

Please follow the official account of GitShare to provide you with more and more high-quality technical tutorials.

Picture note: love to toss about the straw

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

Internet Technology

Wechat

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

12
Report