SpringBoot启动流程
整个启动流程包含,推断 WEB 应⽤类型,设置初始化器,设置 ApplicationListener 监听器,获取并启动 SpringApplicationRunListener 类,准备 Spring 环境,创建并执⾏banner 打印类,创建应⽤上下⽂,准备应⽤上下⽂,刷新应⽤上下⽂,刷新应⽤上下⽂之后的调⽤,执⾏所有的 Runner 运⾏器。
@SpringBootApplicationpublic class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args); }}
初始化主要加载资源类到集合中
推断当前 WEB 应⽤类型(NONE、SERVLET、REACTIVE)设置应⽤上下⽂初始化器设置 ApplicationListener 监听器推断主⼊⼝应⽤类
// 创建⼀个新的实例,这个应⽤上下⽂将从指定的来源加载 Bean
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) { // 初始化资源加载器,默认 null
this.resourceLoader = resourceLoader; // 断⾔主资源不能为空
Assert.notNull(primarySources, \"PrimarySources must not be null\"); // 初始化主要加载资源类集合并去重
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); // 推断当前 WEB 应⽤类型,NONE、SERVLET、REACTIVE
this.webApplicationType = WebApplicationType.deduceFromClasspath(); // 加载引导程序(2.4.0增加的功能)
this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class)); // 设置初始化器
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); // 设置监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); // 推断主⼊⼝应⽤类
this.mainApplicationClass = deduceMainApplicationClass();}
创建引导上下⽂
获取并启动所有 SpringApplicationRunListener 对象创建默认的应⽤参数类准备 Spring 应⽤环境创建并执⾏ banner 打印类创建应⽤上下⽂准备应⽤上下⽂刷新应⽤上下⽂
public ConfigurableApplicationContext run(String... args) { // 创建并启动计时监控类
StopWatch stopWatch = new StopWatch(); stopWatch.start(); // 创建引导上下⽂
DefaultBootstrapContext bootstrapContext = createBootstrapContext(); ConfigurableApplicationContext context = null; // 设置系统属性“java.awt.headless”的值,默认为 true configureHeadlessProperty();
// 创建所有 Spring 运⾏监听器并发布应⽤启动事件,
SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(bootstrapContext, this.mainApplicationClass); try {
// 初始化默认应⽤参数类
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); // 根据运⾏监听器、引导上下⽂、应⽤参数来准备 Spring 环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); // 将要忽略的 bean 参数打开
configureIgnoreBeanInfo(environment); // 创建并执⾏ banner 打印类
Banner printedBanner = printBanner(environment); // 创建应⽤上下⽂
context = createApplicationContext(); // 设置应⽤程序启动 步骤
context.setApplicationStartup(this.applicationStartup); // 准备应⽤上下⽂
prepareContext(bootstrapContext, 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); // 执⾏所有的 Runner 运⾏器
callRunners(context, applicationArguments); }
catch (Throwable ex) {
handleRunFailure(context, ex, listeners); throw new IllegalStateException(ex); } try {
// 发布应⽤上下⽂就绪事件 listeners.running(context); }
catch (Throwable ex) {
handleRunFailure(context, ex, null); throw new IllegalStateException(ex); }
return context;}
创建并启动引导上下⽂,2.4.0 之后的版本增加的新功能
private DefaultBootstrapContext createBootstrapContext() {
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext(); this.bootstrappers.forEach((initializer) -> initializer.intitialize(bootstrapContext)); return bootstrapContext;}
// 从 META-INF/spring.factories 中获取所有的配置类,并将其封装到 SpringApplicationRunListeners 对象中去,主要创建的对象为 EventPublishingRunListenerprivate SpringApplicationRunListeners getRunListeners(String[] args) { Class>[] types = new Class>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args), this.applicationStartup);}
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); }}
void starting(ConfigurableBootstrapContext bootstrapContext, Class> mainApplicationClass) { doWithListeners(\"spring.boot.application.starting\ (step) -> {
if (mainApplicationClass != null) {
step.tag(\"mainApplicationClass\ } });}
// ⼴播事件
public void starting(ConfigurableBootstrapContext bootstrapContext) { this.initialMulticaster
.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));}
// applicationStartingEvent 是 SpringBoot 框架最早执⾏的监听器,在该监听器执⾏ started ⽅法时,会继续发布事件,主要是基于 Spring 的事件机制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); } }}
// 返回与给定事件匹配的监听器
protected Collection Class> sourceType = (source != null ? source.getClass() : null); ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType); // Potential new retriever to populate CachedListenerRetriever newRetriever = null; // Quick check for existing entry on ConcurrentHashMap CachedListenerRetriever existingRetriever = this.retrieverCache.get(cacheKey); if (existingRetriever == null) { // Caching a new ListenerRetriever if possible if (this.beanClassLoader == null || (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) { newRetriever = new CachedListenerRetriever(); existingRetriever = this.retrieverCache.putIfAbsent(cacheKey, newRetriever); if (existingRetriever != null) { newRetriever = null; // no need to populate it in retrieveApplicationListeners } } } if (existingRetriever != null) { Collection // If result is null, the existing retriever is not fully populated yet by another thread. // Proceed like caching wasn't possible for this current local attempt. } return retrieveApplicationListeners(eventType, sourceType, newRetriever);} Source 继承⾃ SimpleCommandLinePropertySource,⽤于解析简单的命令⾏参数 public DefaultApplicationArguments(String... args) { Assert.notNull(args, \"Args must not be null\"); this.source = new Source(args); this.args = args;} private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) { // Create and configure the environment // 创建或者获取应⽤环境 ConfigurableEnvironment environment = getOrCreateEnvironment(); // 配置应⽤环境 configureEnvironment(environment, applicationArguments.getSourceArgs()); ConfigurationPropertySources.attach(environment); // listeners 环境准备,⼴播 ApplicationEnvironmentPreparedEvent listeners.environmentPrepared(bootstrapContext, environment); // 附加配置源 DefaultPropertiesPropertySource.moveToEnd(environment); // 配置其他激活⽂件 configureAdditionalProfiles(environment); // 将环境绑定给当前应⽤程序 bindToSpringApplication(environment); if (!this.isCustomEnvironment) { environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass()); } // 配置 propertySource 对它⾃⼰的递归依赖 ConfigurationPropertySources.attach(environment); return environment;} 打印 banner 的详细操作过程 private Banner printBanner(ConfigurableEnvironment environment) { if (this.bannerMode == Banner.Mode.OFF) { return null; } ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader : new DefaultResourceLoader(null); SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner); if (this.bannerMode == Mode.LOG) { return bannerPrinter.print(environment, this.mainApplicationClass, logger); } return bannerPrinter.print(environment, this.mainApplicationClass, System.out);} 根据不同的应⽤类型初始化不同的⼭下⽂应⽤类 protected ConfigurableApplicationContext createApplicationContext() { return this.applicationContextFactory.create(this.webApplicationType);} private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListener // 设置应⽤上下⽂的 environment context.setEnvironment(environment); // 应⽤⼭下⽂的后置处理 postProcessApplicationContext(context); // 为上下⽂应⽤所有初始化器,执⾏前⾯设置的 ApplicationContextInitializer 类 applyInitializers(context); // 触发所有 SpringApplicationRunListener 监听器的 contextPrepared 事件⽅法。添加所有的事件监听器 listeners.contextPrepared(context); bootstrapContext.close(context); // 记录启动⽇志 if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } // Add boot specific singleton beans // 注册启动参数bean,将容器指定的参数封装成bean,注⼊容器 ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton(\"springApplicationArguments\ if (printedBanner != null) { beanFactory.registerSingleton(\"springBootBanner\ } if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory) .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } if (this.lazyInitialization) { context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); } // Load the sources // 加载所有资源 Set