
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
- Infer the type of the current project
- Load configuration in spring The types in ApplicationContextInitializer in the factories file are instantiated and stored in initializers.
- Similar to step 2, complete the initialization of the listener and store the instantiated listener object in the listeners member variable
- 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
- A task execution observer is created to count the start time
- Declare the ConfigurableApplicationContext object
- Declaring a collection container to store the SpringBootExceptionReporter starts the wrong callback interface
- Set Java awt. System properties of headless
- Get the listener (eventpublishing runlistener) initialized between us and trigger the starting event
- Create ApplicationArguments, which is an application parameter holding class
- Creating a ConfigurableEnvironment is an object that configures the environment
- Configure the BeanInfo information that needs to be ignored
- Configure the Banner information object
- Create a context object for the object
- The callback exception handler that loads the configured startup exception
- Refreshing the application context is essentially to complete the initialization of the Spring container
- Start end record start time
- Complete the corresponding event broadcast
- 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.