A Spring Boot 2.1.7 startup is a sequence of preparation steps, not a single leap from main to a running server. SpringApplication gathers initializers and listeners, builds an environment, creates the right application context, refreshes it, and then hands control to runners. The order matters because each stage supplies something the next stage expects.
Before run(): building the SpringApplication object
When SpringApplication is instantiated, it already performs four tasks:
- infers the web application type (
webApplicationType) - loads and instantiates
ApplicationContextInitializerclasses. It callsClassLoader.getResourcesforMETA-INF/spring.factories, finds entries keyed byApplicationContextInitializer.class, and creates instances - reads the same
META-INF/spring.factoriesand instantiatesApplicationListenerclasses under theApplicationListener.classkey - infers the class containing the
mainmethod.
The run() sequence
SpringApplication.run() then drives startup.
Listeners and environment
getRunListeners()reads every configuredSpringApplicationRunListenerfromMETA-INF/spring.factoriesand constructs aSpringApplicationRunListenersinstance.- All run listeners receive
starting(), andApplicationStartedEventis published. prepareEnvironment()prepares the environment: - inside it,getOrCreateEnvironment()returns aConfigurableEnvironment; if none exists, it creates aStandardServletEnvironment. -configureEnvironment()configures active profiles, taking them from system environment variables or profiles added throughSpringApplication.setAdditionalProfiles(""). - all run listeners receiveenvironmentPrepared(), andApplicationEnvironmentPreparedEventis published. This is the point where configuration files such asapplication.propertiesare loaded.- The banner is printed.
createApplicationContext()creates anApplicationContextaccording towebApplicationType. ForSERVLET, it creates anAnnotationConfigServletWebServerApplicationContext.
That context constructor creates an AnnotatedBeanDefinitionReader, which checks whether the following objects need to be placed into the Spring context:
// User configuration classes. Implements BeanDefinitionRegistryPostProcessor.
// During container refresh, the post-processor scans Spring and registers beans.
ConfigurationClassPostProcessor
// Configures the Autowired annotation. Implements MergedBeanDefinitionPostProcessor.
AutowiredAnnotationBeanPostProcessor
// Configures the Required annotation. Implements MergedBeanDefinitionPostProcessor.
RequiredAnnotationBeanPostProcessor
// Configures JSR-250 annotations. Implements InstantiationAwareBeanPostProcessor.
CommonAnnotationBeanPostProcessor
// Configures JPA annotations.
PersistenceAnnotationBeanPostProcessor
// Configures the EventListener annotation. Implements SmartInitializingSingleton.
EventListenerMethodProcessor
// EventListener factory.
DefaultEventListenerFactory
Preparing the context
prepareContext()prepares the application context: -context.setEnvironment(environment)assigns the environment to theApplicationContext. -postProcessApplicationContext(context)configures theResourceLoaderandClassLoaderproperties. -applyInitializers(context)takes theApplicationContextInitializersubclasses found earlier and callsinitialize()on each. - all run listeners receivecontextPrepared(), andApplicationContextInitializedEventis published.
Refreshing the context
refreshContext()refreshes the context. Underneath, it callsAbstractApplicationContext.refresh(), which proceeds through these steps:prepareRefresh()prepares the context for refresh.obtainFreshBeanFactory()initializes theBeanFactory.prepareBeanFactory(beanFactory)fills theBeanFactorywith various capabilities.postProcessBeanFactory(beanFactory)adds post-processors. When Tomcat is being created, this post-processor is used to initialize the TomcatServerclass.invokeBeanFactoryPostProcessors(beanFactory)activates the variousBeanFactoryprocessors. The main work here is done byConfigurationClassPostProcessor, which was injected throughAnnotatedBeanDefinitionReader, to handle component injection.registerBeanPostProcessors(beanFactory)registers theBeanPostProcessors that intercept bean creation. This is only registration; they are actually called when beans are obtained.initMessageSource()initializes the context message source for internationalization. If the container does not have one, it creates aDelegatingMessageSource, and registers it in the Spring container.initApplicationEventMulticaster()initializes the application event multicaster and puts it in theapplicationEventMulticasterbean. If the container does not have one, it creates aSimpleApplicationEventMulticasterevent dispatcher and registers it in the Spring container.onRefresh()is left to subclasses to initialize other beans, mainly embedded servers such as Tomcat.ServletWebServerApplicationContextimplementsonRefresh()fromAbstractApplicationContext, and its underlying method callscreateWebServer()to create theWebServercontainer.registerListeners()finds listener beans among the registered beans and registers them with the event multicaster.finishBeanFactoryInitialization(beanFactory)initializes the remaining non-lazy singletons.-
finishRefresh()completes the refresh process, notifies the lifecycle processorlifecycleProcessor, and sends aContextRefreshEventto notify others. -
afterRefresh()is called. - All run listeners receive
started(). callRunners()runs runners: it findsApplicationRunnerorCommandLineRunnerbeans in the IoC container and executes theirrunmethods. This is the hook to use when application-specific logic must run at startup.- All run listeners receive
running().