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.