Spring 启动流程源码分析
Spring的启动流程是一个复杂但有序的过程,它涉及到配置文件的加载、IoC容器的创建、Bean的实例化与依赖注入、初始化方法的调用以及监听器的通知等多个阶段。以下是对Spring启动流程的详细解析:
程序入口
SpringBoot项目默认的程序入口是SpringApplication.run(Class<?> primarySource,String... args)
这个静态方法返回一个ConfigurableApplicationContext
类型的应用上下文
-
记录启动时间:
方法一开始,通过System.nanoTime()
记录启动时间,用于后续计算启动耗时。 -
创建Bootstrap上下文:
创建DefaultBootstrapContext
实例,这个上下文主要用于在Spring应用的早期阶段(即在ApplicationContext创建之前)加载和配置一些特定的bean。 -
配置无头模式属性:
调用configureHeadlessProperty()
方法,根据系统的java.awt.headless
属性来配置Java应用的无头模式(没有图形用户界面的模式)。 -
获取并启动SpringApplicationRunListeners:
通过getRunListeners(args)
获取SpringApplicationRunListeners
实例,这些监听器用于在应用启动的不同阶段接收通知。然后调用listeners.starting(...)
通知所有监听器应用即将开始启动。 -
准备环境:
准备ConfigurableEnvironment
,这是Spring应用的环境抽象,包含配置属性和配置源。环境准备阶段会解析命令行参数,并加载application.properties
或application.yml
等配置文件。 -
打印Banner:
如果配置了Banner(启动时的logo或信息),则打印到控制台。 -
创建ApplicationContext:
创建并初始化ConfigurableApplicationContext
实例,这是Spring的核心,用于管理应用中的bean。 -
准备上下文:
调用prepareContext(...)
方法准备ApplicationContext,包括设置环境、加载bean定义等。 -
刷新上下文:
调用refreshContext(context)
方法,这是Spring框架中非常重要的一个步骤,用于完成ApplicationContext的初始化,包括bean的创建、依赖注入等。 -
应用后处理:
在上下文刷新之后,调用afterRefresh(context, applicationArguments)
方法,允许进行一些额外的后处理操作。 -
记录启动耗时:
计算并记录应用启动所花费的时间。 -
通知监听器应用已启动:
调用listeners.started(context, timeTakenToStartup)
通知所有监听器应用已经启动。 -
调用Runner:
如果有CommandLineRunner
或ApplicationRunner
的实现,则调用它们的run
方法,这些Runner通常用于在应用启动后执行一些初始化操作。 -
处理异常:
如果在启动过程中遇到异常,则调用handleRunFailure(context, var12, listeners)
处理异常,并重新抛出IllegalStateException
。 -
通知监听器应用已就绪:
如果没有在启动过程中抛出异常,则调用listeners.ready(context, timeTakenToReady)
通知所有监听器应用已经就绪。 -
返回ApplicationContext:
最后,返回ConfigurableApplicationContext
实例,供外部使用。
整个过程涵盖了Spring Boot应用从启动到就绪的各个环节,包括环境准备、上下文创建与刷新、Runner调用等。通过SpringApplicationRunListeners,还允许用户在应用启动的不同阶段插入自定义逻辑。