Spring boot source code core source code explanation

Posted by leon_nerd on Fri, 07 Jan 2022 03:57:43 +0100

Analysis of SpringBoot source code

  we need to analyze the source code of a framework. It can't be done in one article. In this article, we'll analyze the main process in the source code of SpringBoot. First master the core operation of SpringBoot project startup, and then we will go deep into each specific implementation detail. Note: the source code of this series is based on SpringBoot 2 2.5. Release version to explain

1. Entry for springboot startup

  when we start a SpringBoot project, the entry program is the main method, and a run method is executed in the main method.

@SpringBootApplication
public class StartApp {

	public static void main(String[] args) {
		SpringApplication.run(StartApp.class);
	}
}

2.run method

  then we go into the run() method. The code is relatively simple

	public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
		// Call the overloaded run method to encapsulate the passed Class object into an array
		return run(new Class<?>[] { primarySource }, args);
	}

    called an overloaded run() method to encapsulate the class object we passed in as an array, that's all. We then enter the run() method.

	public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		// Creates a SpringApplication object and calls its run method
		// 1. First look at the logic in the construction method
		// 2. Then look at the logic of the run method
		return new SpringApplication(primarySources).run(args);
	}

  a SpringApplication object is created in this method. At the same time, the run method of the SpringApplication object is called. The logic here has branches. Let's take a look at the logic in the construction method of spring application

3. Spring application constructor

  let's enter the construction method of spring application and look at the core code

	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		// The passed resourceLoader is null
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		// Record the configuration class name of the main method
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		// Record the type of the current project
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		// Load configuration in spring The type corresponding to the ApplicationContextInitializer in the factories file and instantiate it
		// The loaded data is stored in the initializers member variable.
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		// Initialize the listener and store the loaded listener instance object in the listeners member variable
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		// The Class object where the main method is located is pushed back and recorded in the mainApplicationClass object
		this.mainApplicationClass = deduceMainApplicationClass();
	}

  several core operations are completed in this method

  1. Infer the type of the current project
  2. Load configuration in spring The types in ApplicationContextInitializer in the factories file are instantiated and stored in initializers.
  3. Similar to step 2, complete the initialization of the listener and store the instantiated listener object in the listeners member variable
  4. Backstepping the Class object where the main method is located through StackTrace

  the specific implementation details of the above core operations will be analyzed in the following detailed articles

4.run method

  next, let's go back to spring application In the run () method.

	public ConfigurableApplicationContext run(String... args) {
		// Create a task execution observer
		StopWatch stopWatch = new StopWatch();
		// Start execution record execution time
		stopWatch.start();
		// Declare the ConfigurableApplicationContext object
		ConfigurableApplicationContext context = null;
		// Declare the callback interface used by the collection container to store SpringBootExceptionReporter startup errors
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		// Set a named Java awt. System properties of headless
		// Actually, I want to set up the application and allow it to start even if no display is detected
		//For the server, it does not need a display, so it should be set like this
		configureHeadlessProperty();
		// Get the spring applicationrunlistener and load the EventPublishingRunListener
		// Get listener at startup
		SpringApplicationRunListeners listeners = getRunListeners(args);
		// Trigger start event
		listeners.starting();
		try {
			// Construct a parameter holding class for an application
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			// Create and configure environment
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			// Configure the BeanInfo information that needs to be ignored
			configureIgnoreBeanInfo(environment);
			// Output Banner information
			Banner printedBanner = printBanner(environment);
			// Create application context object
			context = createApplicationContext();
			// Load configured startup exception handler
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			// Action before refresh
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			// Refresh the application context to complete the initialization of the Spring container
			refreshContext(context);
			// Post refresh operation
			afterRefresh(context, applicationArguments);
			// End record start time
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			// Event broadcast start completed
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			// Error starting event broadcast
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}
		try {
			// The listener is running
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		// Return context object -- > spring container object
		return context;
	}

  in this method, many core operations of SpringBoot project startup are completed. Let's summarize the above steps

  1. A task execution observer is created to count the start time
  2. Declare the ConfigurableApplicationContext object
  3. Declaring a collection container to store the SpringBootExceptionReporter starts the wrong callback interface
  4. Set Java awt. System properties of headless
  5. Get the listener (eventpublishing runlistener) initialized between us and trigger the starting event
  6. Create ApplicationArguments, which is an application parameter holding class
  7. Creating a ConfigurableEnvironment is an object that configures the environment
  8. Configure the BeanInfo information that needs to be ignored
  9. Configure the Banner information object
  10. Create a context object for the object
  11. The callback exception handler that loads the configured startup exception
  12. Refreshing the application context is essentially to complete the initialization of the Spring container
  13. Start end record start time
  14. Complete the corresponding event broadcast
  15. Returns the application context object.

    the main flow of the code for the startup and initialization of this SpringBoot project is completed. The details will be explained in detail later.