Table of contents
The previous article analyzed the startup class annotations and the SpringApplication constructor.
SpringApplication::run
Start a spring application, create and refresh a new ApplicationContext
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
// 一
stopWatch.start();
// 二
ConfigurableApplicationContext context = null;
// 三
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 四
configureHeadlessProperty();
// 五
SpringApplicationRunListeners listeners = getRunListeners(args);
// 六
listeners.starting();
try {
// 七
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 八
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 九
configureIgnoreBeanInfo(environment);
// 十
Banner printedBanner = printBanner(environment);
// 十一
context = createApplicationContext();
// 十二
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 十三
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 十四
refreshContext(context);
// 十五
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 十六
listeners.started(context);
// 十七
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
// 十八
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
one
It is a timer tool class, where the startup time of the project is first recorded
two
Initialize the application context
three
Initialize exception reporter
Four
Set java.awt.headless to true
If it is true, it tells the system not to expect the normal operation of the display, mouse, keyboard, etc., this is a server-side program, and you need to simulate it by yourself when using these peripherals
five
let's click in
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
We saw the getSpringFactoriesInstances method again (if you don’t remember, you can return to SpringBoot process analysis (1) to review), it uses SpringApplicationRunListener as the key, and the value obtained is org.springframework.boot.context.event.EventPublishingRunListener (from spring.factories obtain). Finally put it into the collection and return.
six
click in
public void starting() {
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
First look at initialMulticaster
The initialMulticaster is initialized when the EventPublishingRunListener is initialized
public EventPublishingRunListener(SpringApplication application, String[] args) { this.application = application; this.args = args; this.initialMulticaster = new SimpleApplicationEventMulticaster(); for (ApplicationListener<?> listener : application.getListeners()) { this.initialMulticaster.addApplicationListener(listener); } }
再看new ApplicationStartingEvent(this.application, this.args)
Constructed an ApplicationStartingEvent
public EventObject(Object source) { if (source == null) throw new IllegalArgumentException("null source"); this.source = source; }
Finally look at multicastEvent
First obtain the appropriate listener according to the event type, and then traverse these appropriate listeners, each listener opens an independent thread to perform monitoring
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); Executor executor = getTaskExecutor(); for (ApplicationListener<?> listener : getApplicationListeners(event, type)) { if (executor != null) { executor.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event); } } }
seven
Parsing startup parameters
eight
Parse the configuration environment, such as configuration files, system variables, etc., and broadcast the environment variable preparation event through the listener
Nine
By default the system property is set spring.beaninfo.ignore
to true.
Guarantees that certain beans are not added to the prepared environment.
ten
print banner
eleven
Initialize the spring context according to webApplicationType
twelve
Initialize the configured exception report class
Thirteen
prepare context
It is mainly divided into 6 steps.
- setEnvironment: Set the context environment
- postProcessApplicationContext: context post-processing, does not do anything by default.
- applyInitializers: Call the initialize method of several ApplicationContextInitializer classes that were instantiated before
- contextPrepared: Notifies listeners that the context has been prepared.
- load: BeanDefinitionLoader can load various beans, such as annotation, XML, package and other types of beans, and then use BeanDefinitionLoader to load these beans into the context.
- contextLoaded: Notifies listeners that the context has been loaded.
fourteen
Refresh context (belongs to spring knowledge)
fifteen
Empty implementation, you can customize your own implementation
sixteen
Publish start complete event
seventeen
If there is a bean of type ApplicationRunner or CommandLineRunner, the run function is triggered to start the task.
eighteen
Monitor the application context to run