One, foreword

In the previous article, we learned about the loading process of new SpringApplication(primarySources) instance initialization source code, and analyzed the basic initialization process by walking through the source code as follows:

1. Resource initialization The resource loader is null

2. Assert that the main loading resource class cannot be null; otherwise, an error is reported

3. Initialize the main load resource class set and deduplicate it

4. Infer the current WEB application type

5. Set the application context initializer

6. Set the listener

7. Infer the main entry application class

If you have forgotten, you can go to review the previous article to understand the core principle of SpringBoot (two) ——– initialization process (run method). So, let’s move on to the core run method in this article.

The SpringApplication instance run method runs the process


As before, let’s look at the overall process implementation in the RUN method:

public ConfigurableApplicationContext run(String... args) {
		// create and start the timer monitor class
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		
		// Initialize the application context and exception report collection
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		
		// 3. Set the system property 'java.awt.headless' to true
		configureHeadlessProperty();
		
		// 4. Create all Spring run listeners and publish application start events
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			
			// 5. Initialize the default application parameter class
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			
			// Prepare the Spring environment based on run listeners and application parameters
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			
			// create Banner print class
			Banner printedBanner = printBanner(environment);
			
			// Create an application context
			context = createApplicationContext();
			
			// 9. Prepare the exception reporter
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			
			// prepare the application context
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			
			// refresh the application context
			refreshContext(context);
			
			// 12. Post-process the application context refresh
			afterRefresh(context, applicationArguments);
			
			 // Stop the timer monitoring class
			stopWatch.stop();
			
			// 14. Output logs to record the name and time of the execution main class
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			
			Publish the application context startup completion event
			listeners.started(context);
			
			// Execute all runners
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			
			// 17. Publish the application context ready event
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		// Return the application context
		return context;
	}
Copy the code

3. Decomposition of the running process of run method

3.1 Create and start a timing monitoring class

		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
Copy the code

Enter start() as follows:

	/**
	 * Start an unnamed task. The results are undefined if {@link #stop()}
	 * or timing methods are called without invoking this method.
	 * @see #stop()
	 */
	public void start(a) throws IllegalStateException {
		start("");
	}

	/**
	 * Start a named task. The results are undefined if {@link #stop()}
	 * or timing methods are called without invoking this method.
	 * @param taskName the name of the task to start
	 * @see #stop()
	 */
	public void start(String taskName) throws IllegalStateException {
		if (this.currentTaskName ! =null) {
			throw new IllegalStateException("Can't start StopWatch: it's already running");
		}
		this.currentTaskName = taskName;
		this.startTimeMillis = System.currentTimeMillis();
	}
Copy the code

It first records the name of the current task, which defaults to an empty string, and then the start time of the current Spring Boot application.

3.2 Initializing the application Context and exception report collection

		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
Copy the code

3.3 Setting the system property Java.awt. headless

        configureHeadlessProperty();
Copy the code

As to why set this property value to true, you can refer to the following article: www.cnblogs.com/princessd82…

3.4 Create all Spring run listeners and publish application start events

		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
Copy the code

To create a Spring runtime listener, go to the source code:

	private SpringApplicationRunListeners getRunListeners(String[] args) { Class<? >[] types =newClass<? >[] { SpringApplication.class, String[].class };return new SpringApplicationRunListeners(logger,
				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
	}
SpringApplicationRunListeners {
        ......
		SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
		this.log = log;
		this.listeners = newArrayList<>(listeners); }... }Copy the code

Before creating logic and instantiate the initializer and listener, as is called getSpringFactoriesInstances method to get the configuration of the listener name and instantiate all the classes. SpringApplicationRunListener all listener configuration in the spring – the boot – 2.0.4. The jar! / meta-inf /spring.factories:

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
Copy the code

3.5 Initializing the Default Application Parameter Class

			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
Copy the code

3.6 Prepare the Spring environment based on run listeners and application parameters

			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
Copy the code

Here we mainly look at the prepareEnvironment source:

	private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
		// 1.Create the environment
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		// 2.Configure the environment
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		listeners.environmentPrepared(environment);
		bindToSpringApplication(environment);
		if (!this.isCustomEnvironment) {
			environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
					deduceEnvironmentClass());
		}
		ConfigurationPropertySources.attach(environment);
		return environment;
	}
Copy the code

3.7 Creating the Banner Print Class

			Banner printedBanner = printBanner(environment);
Copy the code

3.8 Creating an Application Context

			context = createApplicationContext();
Copy the code

Go into the source code, you can know that here is mainly based on different application types to initialize different context application classes.

3.9 Preparing an exception reporter

			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
Copy the code

GetSpringFactoriesInstances — — — — — – > > createSpringFactoriesInstances — — — — — — — > > > before the logic and instantiate the initializer and listener, Call is getSpringFactoriesInstances method to get the exception class name of the configuration and instantiate all exception handling classes. The exception reporting class is configured in spring-boot-2.0.4.release.jar! / meta-inf /spring.factories

# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers
Copy the code

3.10 Preparing the Application Context

			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
Copy the code

Next, enter the prepareContext method:

	private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
		context.setEnvironment(environment);
		// Configure the context's bean generator and resource loader
		postProcessApplicationContext(context);
		// Apply all initializers to the context
		applyInitializers(context);
		/ / triggers all SpringApplicationRunListener contextPrepared event listener method
		listeners.contextPrepared(context);
		// Log
		if (this.logStartupInfo) {
			logStartupInfo(context.getParent() == null);
			logStartupProfileInfo(context);
		}

		// Add boot Specific singleton beans start two special singleton beans
		context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments);
		if(printedBanner ! =null) {
			context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
		}

		// Load the sources
		Set<Object> sources = getAllSources();
		Assert.notEmpty(sources, "Sources must not be empty");
		load(context, sources.toArray(new Object[0]));
		/ / triggers all SpringApplicationRunListener contextLoaded event listener method
		listeners.contextLoaded(context);
	}
Copy the code

3.11 Refreshing the Application Context

			refreshContext(context);
Copy the code

3.12 Custom processing after the application Context is refreshed

			afterRefresh(context, applicationArguments);

	protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {}Copy the code

3.13 Stopping the Timing Monitoring class

			stopWatch.stop();
Copy the code

The timer listener stops and some task execution information is counted.

3.14 Output Logs This section records the name and time of the execution main class

			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
Copy the code

3.15 Publishing the Application Context Startup Completion event

			listeners.started(context);
Copy the code

Here will trigger all SpringApplicationRunListener started event listener method.

3.16 Run all Runner runners

			callRunners(context, applicationArguments);
Copy the code

Execute all ApplicationRunner and CommandLineRunner executors

3.17 Publishing an Application Context Ready Event

			listeners.running(context);
Copy the code

Trigger all SpringApplicationRunListener listener running event method.

3.18 Returning the Application Context

		return context;
Copy the code

Four,

About SpringBootApplication. The run () to start the instance initialization and load the run method source code analysis to this end, analysis of the source code is a bit painful thing, but after analysis of the source code, you’ll know how SpringBoot load and initialize a more comprehensive understanding, Of course, there are some other things worth learning, such as Spring event monitoring, how to use singletons, automatic configuration and so on. Finally, I hope to give you a little help on the way to learn SpringBoot. After watching it, if you feel there is a harvest, I hope to click on the like.